I am trying to implement Circular ProgressBar in one of my fragment.
I want to attain this using AsyncTask class along with other background process and I want that progress bar to update on onProgressUpdate() method too.
Here's my Fragment implementing ProgressBar:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
rootView = inflater.inflate(R.layout.playlist_fragment, container, false);
// Setting up progressBar
progressBar = (ProgressBar) rootView.findViewById(R.id.progressBar);
progressBar.setProgress(0);
return rootView;
}
Calling AsyncTask class from within Fragment which says cannot resolve method at setProgressBr(). I think I am not appropriately passing the parameters.
new GetPlaylistAsyncTask(mYouTubeDataApi,getContext(),PlaylistFragment.this)
.setProgressBar(progressBar)
.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());
Here's my AsyncTask class:
public class GetPlaylistAsyncTask extends AsyncTask<String, Integer, Pair<String, List<Video>>> {
private static final String TAG = "GetPlaylistAsyncTask";
private static final Long YOUTUBE_PLAYLIST_MAX_RESULTS = 10L;
//see: https://developers.google.com/youtube/v3/docs/playlistItems/list
private static final String YOUTUBE_PLAYLIST_PART = "snippet";
private static final String YOUTUBE_PLAYLIST_FIELDS = "pageInfo,nextPageToken,items(id,snippet(resourceId/videoId))";
//see: https://developers.google.com/youtube/v3/docs/videos/list
private static final String YOUTUBE_VIDEOS_PART = "snippet,contentDetails,statistics"; // video resource properties that the response will include.
private static final String YOUTUBE_VIDEOS_FIELDS = "items(id,snippet(title,description,thumbnails/high),contentDetails/duration,statistics)"; // selector specifying which fields to include in a partial response.
private YouTube mYouTubeDataApi;
Context mContext;
ProgressBar bar;
private AsyncResponse theListener;
public void setProgressBar(ProgressBar bar) {
this.bar = bar;
}
public GetPlaylistAsyncTask(YouTube api, Context context, PlaylistFragment frag ) {
mYouTubeDataApi = api;
mContext = context;
theListener = (AsyncResponse)frag;
}
#Override
protected Pair<String, List<Video>> doInBackground(String... params) {
final String playlistId = params[0];
final String nextPageToken;
if (params.length == 2) {
nextPageToken = params[1];
} else {
nextPageToken = null;
}
PlaylistItemListResponse playlistItemListResponse;
try {
playlistItemListResponse = mYouTubeDataApi.playlistItems()
.list(YOUTUBE_PLAYLIST_PART)
.setPlaylistId(playlistId)
.setPageToken(nextPageToken)
.setFields(YOUTUBE_PLAYLIST_FIELDS)
.setMaxResults(YOUTUBE_PLAYLIST_MAX_RESULTS)
.setKey(ApiKey.YOUTUBE_API_KEY)
.execute();
} catch (IOException e) {
e.printStackTrace();
return null;
}
if (playlistItemListResponse == null) {
Log.e(TAG, "Failed to get playlist");
return null;
}
List<String> videoIds = new ArrayList();
// pull out the video id's from the playlist page
for (PlaylistItem item : playlistItemListResponse.getItems()) {
videoIds.add(item.getSnippet().getResourceId().getVideoId());
}
// get details of the videos on this playlist page
VideoListResponse videoListResponse = null;
try {
videoListResponse = mYouTubeDataApi.videos()
.list(YOUTUBE_VIDEOS_PART)
.setFields(YOUTUBE_VIDEOS_FIELDS)
.setKey(ApiKey.YOUTUBE_API_KEY)
.setId(TextUtils.join(",", videoIds)).execute();
} catch (IOException e) {
e.printStackTrace();
}
return new Pair(playlistItemListResponse.getNextPageToken(), videoListResponse.getItems());
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Integer... values) {
if (this.bar != null) {
bar.setProgress(values[0]);
}
}
#Override
protected void onPostExecute(Pair<String, List<Video>> result) {
theListener.handleGetPlaylistResult(null,result);
}
}
Will appreciate a quick fix for the above problem. Thanks in advance.
.setProgressBar(progressBar) method has a return type void so you cannot chain the calls like this
new GetPlaylistAsyncTask(mYouTubeDataApi,getContext(),PlaylistFragment.this)
.setProgressBar(progressBar)
.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());
Change your setProgressBar() method to the following and it should work
public GetPlaylistAsyncTask setProgressBar(ProgressBar bar) {
this.bar = bar;
return this;
}
OR
If you don't want to change the method signature then do the following
final GetPlaylistAsyncTask getPlaylistAsyncTask = new GetPlaylistAsyncTask(mYouTubeDataApi,getContext(),PlaylistFragment.this);
getPlaylistAsyncTask.setProgressBar(progressBar);
getPlaylistAsyncTask.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());
Also make sure both params playlistVideos.playlistId, playlistVideos.getNextPageToken() are Strings.
You can do like this
GetPlaylistAsyncTask playAsync=new (mYouTubeDataApi,getContext(),PlaylistFragment.this);
playAsync.setProgressBar(progressBar);
playAsync.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());
Hope this will work for you.
You are calling methods in chain . In that way each method should returns the current instance on which its called . Modify your method as below it will work.
public GetPlaylistAsyncTask setProgressBar(ProgressBar bar) {
this.bar = bar;
return this;
}
You cant just add progress directly to a circular progress bar, Here is what I did to resolve this issue.
add a drawable file circular_progress.xml
<?xml version="1.0" encoding="utf-8"?>
<item android:id="#android:id/secondaryProgress">
<shape
android:innerRadius ="15dp"
android:shape="ring"
android:useLevel="true"
android:thickness="4dp" >
<gradient
android:endColor="#color/blackBackground"
android:startColor="#color/blackBackground"
android:type="sweep" />
</shape>
</item>
<item android:id="#android:id/progress">
<rotate
android:fromDegrees="270"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="270" >
<shape
android:innerRadius ="15dp"
android:shape="ring"
android:useLevel="true"
android:thickness="4dp">
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
<gradient
android:endColor="#e1c25b"
android:startColor="#e1c25b"
android:type="sweep" />
</shape>
</rotate>
</item>
in your fragment layout add a progress bar
<ProgressBar
android:id="#+id/pb_download"
style="#style/Base.Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:max="100"
android:progress="75"
android:progressDrawable="#drawable/circular_progress" />
now you can use setProgress() to update the progress.
Feel free to ask any doubts.
Related
I am following this guide to learn about 'Creating App Settings using Preference Headers'. This question deals with "Supporting older (than HoneyComb) versions with preference headers".
I think I have followed all the steps, but still am getting this exception. So what am I missing?
LOG:
...
07-10 18:45:31.935: E/AndroidRuntime(1285): FATAL EXCEPTION: main
07-10 18:45:31.935: E/AndroidRuntime(1285): java.lang.RuntimeException: Unable to start activity ComponentInfo{practice_projects.minimalpreferencesusingpreferenceheadersoldversions/practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceActivity}: java.lang.ClassCastException: practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceFragment cannot be cast to android.app.Fragment
...
07-10 18:45:31.935: E/AndroidRuntime(1285): Caused by: java.lang.ClassCastException: practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceFragment cannot be cast to android.app.Fragment
...
07-10 18:45:31.935: E/AndroidRuntime(1285): at practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceActivity.onCreate(MyPreferenceActivity.java:16)
...
MainActivity.java:
public class MainActivity extends FragmentActivity implements DrawerLayout.DrawerListener, ListView.OnItemClickListener {
private static final String TAG = MainActivity.class.getSimpleName();
private final String [] drawerListItems = {"Settings"};
private DrawerLayout drawerLayout;
private FrameLayout frameLayout;
private ListView drawerListView;
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//******LINE # 16***********
drawerListView = (ListView) findViewById(R.id.mainActivity_listView);
drawerListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, drawerListItems));
drawerListView.setOnItemClickListener(this);
drawerLayout = (DrawerLayout) findViewById(R.id.mainActivity_drawerLayout);
drawerLayout.setDrawerListener(this);
frameLayout = (FrameLayout) findViewById(R.id.mainActivity_frameLayout);
textView = (TextView) findViewById(R.id.mainActivity_textView);
}
/****************************************************************************************************************************************/
/************************************************DrawerLayout.DrawerListener IMPLEMENTATION**********************************************/
/****************************************************************************************************************************************/
#Override
public void onDrawerClosed(View arg0) {
frameLayout.setBackgroundColor(Color.parseColor("#6A0888")); /* Dark Purple Color */
}
#Override
public void onDrawerOpened(View arg0) {
frameLayout.setBackgroundColor(Color.parseColor("#FE642E")); /* Orange Color */
}
#Override
public void onDrawerSlide(View arg0, float arg1) {}
#Override
public void onDrawerStateChanged(int arg0) {}
/****************************************************************************************************************************************/
/************************************************OnDrawerClickListener IMPLEMENTATION**********************************************/
/****************************************************************************************************************************************/
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
frameLayout.setBackgroundColor(Color.parseColor("#F7FE2E")); /* Yellow Color */
startActivity(new Intent(this, MyPreferenceActivity.class));
drawerListView.setItemChecked(position, true);
drawerLayout.closeDrawer(drawerListView);
}
}
MyPreferenceActivity.java:
public class MyPreferenceActivity extends PreferenceActivity {
private static final String TAG = MyPreferenceActivity.class.getSimpleName();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate of MyPreferenceActivity called.");// check
String intentAction = getIntent().getAction();
Log.i(TAG, "The action retrieved from the intent is " + intentAction + ".");// check
if (intentAction != null && intentAction.equals("practice_projects.minimalpreferencesusingpreferenceheadersoldversions.DB")) {
Log.i(TAG, "YES intentAction!=null && intentAction.equals(\"practice_projects.minimalpreferencesusingpreferenceheadersoldversions.DB\"");// check
addPreferencesFromResource(R.xml.db_preferences);
Log.i(TAG, "Added preferences from R.xml.db_preferences.");// check
} else if (intentAction != null && intentAction.equals("practice_projects.minimalpreferencesusingpreferenceheadersoldversions.UI")) {
Log.i(TAG, "YES intentAction!=null && intentAction.equals(\"practice_projects.minimalpreferencesusingpreferenceheadersoldversions.UI\"");// check
addPreferencesFromResource(R.xml.ui_preferences);
Log.i(TAG, "Added preferences from R.xml.ui_preferences.");// check
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
Log.i(TAG, "Build version is LESS than honeycomb.");// check
// Load the preference_headers_legacy.xml
addPreferencesFromResource(R.xml.preference_headers_legacy);
Log.i(TAG, "Added preferences from R.xml.preference_headers_legacy.");// check
} else {
Log.i(TAG, "Build version is HIGHER than honeycomb. "
+ "NO *******intentAction!=null && intentAction.equals(\"practice_projects.minimalpreferencesusingpreferenceheadersoldversions"
+ ".DB\"*******."
+ " NO *******intentAction!=null && intentAction.equals(\"practice_projects.minimalpreferencesusingpreferenceheadersoldversions"
+ ".UI\"*******.");// check
}
}
// Called only on HoneyComb and later
// Although the #TargetApi annotation is not for compiler, and is for Lint only, but no problem, as the system will call this method for honeycomb and later
// only
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
}
MyPreferenceFragment.java:
public class MyPreferenceFragment extends PreferenceFragment {
private static final String TAG = MyPreferenceFragment.class.getSimpleName();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String preferenceHeaderExtraValue = getArguments().getString("preference_extra_key");
if (preferenceHeaderExtraValue!=null) {
if (preferenceHeaderExtraValue.equals("db")) {
//getView().setBackgroundColor(Color.parseColor("#81F7BE")); /* Aqua towards green */ //NPE because the layout is not created yet**********
Log.i(TAG, "The value of the preference intent with the key "+preferenceHeaderExtraValue+" is \"db\".");
addPreferencesFromResource(R.xml.db_preferences);
} else if (preferenceHeaderExtraValue.equals("ui")) {
//getView().setBackgroundColor(Color.parseColor("#A9D0F5")); /* Aqua towards blue */ //NPE because the layout is not created yet**********
Log.i(TAG, "The value of the preference intent with the key "+preferenceHeaderExtraValue+" is \"ui\".");
addPreferencesFromResource(R.xml.ui_preferences);
} else {
Log.i(TAG, "The value of the preference intent with the key "+preferenceHeaderExtraValue+" is neither \"db\" nor \"ui\".");
}
} else {
Log.i(TAG, "getArguments() returns null.");
}
}
}
PreferenceFragment.java (Taken from PreferenceFragment for Pre-HoneyComb by Christophe Beyls):
/**
* A PreferenceFragment for the support library. Based on the platform's code with some removed features and a basic ListView layout.
*
* #author Christophe Beyls https://gist.github.com/cbeyls/7475726
*
*/
public abstract class PreferenceFragment extends Fragment {
private static final int FIRST_REQUEST_CODE = 100;
private static final int MSG_BIND_PREFERENCES = 1;
private static final int MSG_REQUEST_FOCUS = 2;
private static final String PREFERENCES_TAG = "android:preferences";
private static final float HC_HORIZONTAL_PADDING = 16;
#SuppressLint("HandlerLeak")
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_BIND_PREFERENCES:
bindPreferences();
break;
case MSG_REQUEST_FOCUS:
mList.focusableViewAvailable(mList);
break;
}
}
};
private boolean mHavePrefs;
private boolean mInitDone;
private ListView mList;
private PreferenceManager mPreferenceManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class);
c.setAccessible(true);
mPreferenceManager = c.newInstance(this.getActivity(), FIRST_REQUEST_CODE);
} catch (Exception ignored) {
}
}
#Override
public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle savedInstanceState) {
ListView listView = new ListView(getActivity());
listView.setId(android.R.id.list);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
final int horizontalPadding = (int) (HC_HORIZONTAL_PADDING * getResources().getDisplayMetrics().density);
listView.setPadding(horizontalPadding, 0, horizontalPadding, 0);
}
return listView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (mHavePrefs) {
bindPreferences();
}
mInitDone = true;
if (savedInstanceState != null) {
Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
if (container != null) {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
if (preferenceScreen != null) {
preferenceScreen.restoreHierarchyState(container);
}
}
}
}
public void onStop() {
super.onStop();
try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop");
m.setAccessible(true);
m.invoke(mPreferenceManager);
} catch (Exception ignored) {
}
}
public void onDestroyView() {
mList = null;
mHandler.removeCallbacksAndMessages(null);
super.onDestroyView();
}
public void onDestroy() {
super.onDestroy();
try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy");
m.setAccessible(true);
m.invoke(mPreferenceManager);
} catch (Exception ignored) {
}
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
PreferenceScreen preferenceScreen = getPreferenceScreen();
if (preferenceScreen != null) {
Bundle container = new Bundle();
preferenceScreen.saveHierarchyState(container);
outState.putBundle(PREFERENCES_TAG, container);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class);
m.setAccessible(true);
m.invoke(mPreferenceManager, requestCode, resultCode, data);
} catch (Exception ignored) {
}
}
public PreferenceManager getPreferenceManager() {
return mPreferenceManager;
}
public void setPreferenceScreen(PreferenceScreen screen) {
try {
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
m.setAccessible(true);
boolean result = (Boolean) m.invoke(mPreferenceManager, screen);
if (result && (screen != null)) {
mHavePrefs = true;
if (mInitDone) {
postBindPreferences();
}
}
} catch (Exception ignored) {
}
}
public PreferenceScreen getPreferenceScreen() {
try {
Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen");
m.setAccessible(true);
return (PreferenceScreen) m.invoke(mPreferenceManager);
} catch (Exception e) {
return null;
}
}
public void addPreferencesFromIntent(Intent intent) {
requirePreferenceManager();
try {
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class);
m.setAccessible(true);
PreferenceScreen screen = (PreferenceScreen) m.invoke(mPreferenceManager, intent, getPreferenceScreen());
setPreferenceScreen(screen);
} catch (Exception ignored) {
}
}
public void addPreferencesFromResource(int resId) {
requirePreferenceManager();
try {
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
m.setAccessible(true);
PreferenceScreen screen = (PreferenceScreen) m.invoke(mPreferenceManager, getActivity(), resId, getPreferenceScreen());
setPreferenceScreen(screen);
} catch (Exception ignored) {
}
}
public Preference findPreference(CharSequence key) {
if (mPreferenceManager == null) {
return null;
}
return mPreferenceManager.findPreference(key);
}
private void requirePreferenceManager() {
if (this.mPreferenceManager == null) {
throw new RuntimeException("This should be called after super.onCreate.");
}
}
private void postBindPreferences() {
if (!mHandler.hasMessages(MSG_BIND_PREFERENCES)) {
mHandler.sendEmptyMessage(MSG_BIND_PREFERENCES);
}
}
private void bindPreferences() {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
if (preferenceScreen != null) {
preferenceScreen.bind(getListView());
}
}
public ListView getListView() {
ensureList();
return mList;
}
private void ensureList() {
if (mList != null) {
return;
}
View root = getView();
if (root == null) {
throw new IllegalStateException("Content view not yet created");
}
View rawListView = root.findViewById(android.R.id.list);
if (rawListView == null) {
throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'");
}
if (!(rawListView instanceof ListView)) {
throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class");
}
mList = (ListView) rawListView;
mHandler.sendEmptyMessage(MSG_REQUEST_FOCUS);
}
preference_headers.xml:
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
<header
android:fragment="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceFragment"
android:title="#string/preferenceHeaders_title1"
android:summary="#string/preferenceHeaders_summary1" >
<extra android:name="preference_extra_key" android:value="db" />
</header>
<header
android:fragment="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceFragment"
android:title="#string/preferenceHeaders_title2"
android:summary="#string/preferenceHeaders_summary2" >
<extra android:name="preference_extra_key" android:value="ui" />
</header>
</preference-headers>
ui_preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<EditTextPreference
android:title="#string/UIPreferences_editTextPreference_title"
android:summary="#string/UIPreferences_editTextPreference_summary"
android:key="preferences_UIPditTextPreference_key"
android:defaultValue="UIPreferences_editTextPreference_defaultValue" />
<EditTextPreference
android:title="#string/UIPreferences_editTextPreference_title1"
android:summary="#string/UIPreferences_editTextPreference_summary1"
android:key="UIPreferences_editTextPreference_key1"
android:defaultValue="UIPreferences_editTextPreference_defaultValue1" />
</PreferenceScreen>
db_preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference
android:title="#string/DBPreferences_checkBoxPreference_title"
android:summary="#string/DBPreferences_checkBoxPreference_summary"
android:key="DBPreferences_checkBoxPreference_key"
android:defaultValue="DBPreferences_checkBoxPreference_defaultValue" />
<CheckBoxPreference
android:title="#string/DBPreferences_checkBoxPreference_title1"
android:summary="#string/DBPreferences_checkBoxPreference_summary1"
android:key="DBPreferences_checkBoxPreference_key1"
android:defaultValue="DBPreferences_checkBoxPreference_defaultValue1" />
</PreferenceScreen>
preference_headers_legacy:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<Preference
android:title="#string/preferenceHeaders_title1"
android:summary="#string/preferenceHeaders_summary1" >
<intent
android:targetPackage="practice_projects.minimalpreferencesusingpreferenceheadersoldversions"
android:targetClass="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceActivity"
android:action="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.DB" />
</Preference>
<Preference
android:title="#string/preferenceHeaders_title2"
android:summary="#string/preferenceHeaders_summary2" >
<intent
android:targetPackage="practice_projects.minimalpreferencesusingpreferenceheadersoldversions"
android:targetClass="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceActivity"
android:action="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.UI" />
</Preference>
</PreferenceScreen>
strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Minimal Preferences Using Preference headers OLD VERSIONS</string>
<string name="mainActivity_textView">I am a TextView.</string>
<string name="preferenceHeaders_title">Preference Header Title</string>
<string name="preferenceHeaders_summary">Preference Header Summary</string>
<string name="preferenceHeaders_title1">Preference Header Title</string>
<string name="preferenceHeaders_summary1">Preference Header Summary</string>
<string name="preferenceHeaders_title2">Preference Header Title</string>
<string name="preferenceHeaders_summary2">Preference Header Summary</string>
<string name="DBPreferences_checkBoxPreference_title">Preference Title</string>
<string name="DBPreferences_checkBoxPreference_summary">Preference Summary</string>
<string name="DBPreferences_checkBoxPreference_defaultValue">DBPreferences_checkBoxPreference_defaultValue</string>
<string name="DBPreferences_checkBoxPreference_title1">Preference Title</string>
<string name="DBPreferences_checkBoxPreference_summary1">Preference Summary</string>
<string name="DBPreferences_checkBoxPreference_defaultValue1">DBPreferences_checkBoxPreference_defaultValue1</string>
<string name="UIPreferences_editTextPreference_title">Preference Title</string>
<string name="UIPreferences_editTextPreference_summary">Preference Summary</string>
<string name="UIPreferences_editTextPreference_defaultValue">UIPreferences_editTextPreference_defaultValue</string>
<string name="UIPreferences_editTextPreference_title1">Preference Title</string>
<string name="UIPreferences_editTextPreference_summary1">Preference Summary</string>
<string name="UIPreferences_editTextPreference_defaultValue1">UIPreferences_editTextPreference_defaultValue1</string>
<string name="title_activity_my_preference">MyPreferenceActivity</string>
<string name="hello_world">Hello world!</string>
</resources>
You can't use my PreferenceFragment to display headers or anything Honeycomb-specific. It's just a hack to allow showing a single Preferences set in an ActionBarActivity, because previously it was not possible to have a compatibility ActionBar in a PreferenceActivity (it's now possible since AppCompat 22.1 so you don't need this class).
I think the support library will soon provide support for preferences on older versions so keep an eye on it.
From the link that you have provided, it looks like the PreferenceFragment that you are using uses android.support.v4.app.Fragment. See you have this line in the imports section in the GitHub page:
import android.support.v4.app.Fragment;
What this does is use the Fragment class from the support library. But somewhere within you code you are expecting an instance of the regular Fragment class found in package android.app.Fragment (see this from your stack trace). You are using the fragment from the support library in a class from the regular library - they are incompatible with each other and will throw the exception that you are seeing. What you really have is a workaround that is not supported.
As a suggestion, see the following answer for more info on backwards compatibility of PreferenceActivity.
EDIT: Including link in answer
PreferenceActivity Android 4.0 and earlier
I want to display a progressbar when my activity load. But the progressbar work only half the time and when the progressbar doesn't work a black screen was display while charging.
This is my AsyncTask:
class Task extends AsyncTask<String, Integer, Boolean> {
#Override
protected void onPreExecute() {
layout.setVisibility(View.VISIBLE);
titre_projet.setVisibility(View.GONE);
description_projet.setVisibility(View.GONE);
image_projet.setVisibility(View.GONE);
super.onPreExecute();
}
#Override
protected void onPostExecute(Boolean result) {
layout.setVisibility(View.GONE);
titre_projet.setVisibility(View.VISIBLE);
description_projet.setVisibility(View.VISIBLE);
image_projet.setVisibility(View.VISIBLE);
super.onPostExecute(result);
}
#Override
protected Boolean doInBackground(String... params) {
try {
runOnUiThread(new Runnable() {
public void run() {
Intent intent = getIntent();
if (intent != null) {
searchResultats(intent.getStringExtra(EXTRA_PROJET));
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
In this code, all in runOnUiThread is my code to display the content.
This is what I have in OnCreate:
image_projet = (ImageView) findViewById(R.id.imageView_projet);
layout = (LinearLayout) findViewById(R.id.progressbar_view);
titre_projet = (TextView) findViewById(R.id.titre_projet);
description_projet = (TextView) findViewById(R.id.description_projet);
new Task().execute();
And my XML for the progressBar:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="50%" android:pivotY="50%" android:fromDegrees="0"
android:toDegrees="360"
android:layout_width="match_parent"
android:layout_height="match_parent">
<shape android:shape="ring" android:innerRadiusRatio="3"
android:thicknessRatio="8" android:useLevel="false">
<size android:width="76dip" android:height="76dip" />
<gradient android:type="sweep" android:useLevel="false"
android:startColor="#447a29"
android:endColor="#447a29"
android:angle="0"
/>
</shape>
</rotate>
When your News Activity starts, start to fetch your data (article). In the onCreate method of Activity, start your task. In the doInBackground method of your Task, fetch the article (I assume you'll need to fetch it through network).
Once your Task is done, update your UI in onPostExecute.
class Task extends AsyncTask<String, Integer, Object> {
private Activity activity;
public Task(Activity a){
activity=a;
}
#Override
protected void onPostExecute(Object article) {
activity.onArticleFetched(article);
}
#Override
protected Object doInBackground(String... params) {
Object article = new Article();
//Fetch article... may take a few seconds, but you don't care because you are not in the UI thread
return article;
}
}
In the Activity, do something like this :
class NewsActivity extends Activity {
#Override
public void onCreate(Bundle a){
super.onCreate(a);
//do some stuff.
task.execute();
progressBar.setVisibility(View.VISIBLE);
}
public void onArticleFetched(Object article){
progressBar.setVisibility(View.GONE);
//updateUI
}
}
You have published drawable instead of layout xml. I haven't any guess how it can be used for indicating progress.
Please check AsyncTask reference. AsyncTask.doInBackground() should be used for obtaining data (networking, parsing and other stuff prohibited in the UI thread). There you time to time need to call AsyncTask.publishProgress() and after that system calls AsyncTask.onProgressUpdate() in the UI thread. Override AsyncTask.onProgressUpdate() to show progress in your UI (set level to progress bar or something else).
At the end AsyncTask.onPostExecute() will be called in the UI thread. Override this method to show data processed in AsyncTask.doInBackground() and modify views as much as you wish.
I'm also getting it in a precise context and the solution given here (IllegalStateException: Can not perform this action after onSaveInstanceState with ViewPager) don't work.
Here is the code: Should be a working code for test; I hope.
MainActivity.java
public class MainActivity extends FragmentActivity {
final static int INIT_NETWORK_DONE = 1;
final static int EXIT_APPLICATION = -1;
private Site site = new Site(this);
private WifiManager wifi = null;
Handler mHandler = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
site.setUrls();
if (savedInstanceState == null) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.replace(R.id.frame_container, new Fragment_init(site)).commit();
}
}
. . .
#Override
public void onSaveInstanceState(Bundle saveInstanceState) {
//super.onSaveInstanceState(saveInstanceState);
}
}
Fragment_init.java
public class Fragment_init extends Fragment {
Fragment fragment = null;
private InitTask mInitTask = null;
// Taille maximale du téléchargement
public final static int MAX_SIZE = 100;
// Identifiant de la boîte de dialogue
public final static int ID_DIALOG = 0;
public final static int DO_INIT_WIFI = 1;
private Site site = null;
public Fragment_init() {
}
public Fragment_init(Site _site) {
site = _site;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_init, container, false);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState == null) {
Animation animation = AnimationUtils.loadAnimation(getActivity().getApplicationContext(), R.animator.welcome_anim);
ImageView logoSite = (ImageView)getActivity().findViewById(R.id.imageAvenArmand);
logoSite.startAnimation(animation);
// Do the init
mInitTask = new InitTask(Fragment_init.this, site, getFragmentManager());
// On l'exécute
mInitTask.execute(0);
}
}
// L'AsyncTask est bien une classe interne statique
static class InitTask extends AsyncTask<Integer, Integer, Integer> {
// Référence faible à l'activité
private Fragment_init mActivity = null;
private Site site = null;
Context context = null;
private FragmentManager fragmentManager = null;
public InitTask (Fragment_init pActivity, Site pSite, FragmentManager _fragmentManager) {
mActivity = pActivity;
context = mActivity.getActivity();
site = pSite;
fragmentManager = _fragmentManager;
}
#Override
protected void onPreExecute () {
}
#Override
protected void onPostExecute (Integer result) {
if(result != 1) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mActivity.getActivity());
alertDialog.setTitle(R.string.label_titleAlertInit);
} else {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.replace(R.id.frame_container, new Fragment_selectLanguage(site)).commitAllowingStateLoss();
}
}
#Override
protected Integer doInBackground (Integer... arg0) {
URL url = null;
BufferedInputStream buf;
ArrayList<Language> languages = null;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
return 1;
}
#Override
protected void onProgressUpdate (Integer... prog) {
}
#Override
protected void onCancelled () {
}
private int processStream(InputStream inputStream) {
// Création du parser XML
XmlPullParserFactory factory;
int lineNumber = 0;
return (1);
}
}
#Override
public void onSaveInstanceState(Bundle saveInstanceState) {
//super.onSaveInstanceState(saveInstanceState);
}
}
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:screenOrientation="portrait"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.cabbonline.ndguidelt.MainActivity" >
</FrameLayout>
fragment_init.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragmentInit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.cabbonline.ndguidelt.MainActivity" >
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:src="#drawable/launcher_icon" />
</RelativeLayout>
Anyway, I think that not calling super.onSaveInstanceState() should cause problem on context saving no?
so if you rotate the screen when the image is fading, you should get IllegalStateException on call on commit()
So my workaround is to prevent the screen rotation during this transitional screen. Ok that's ok for me but I doubt it could be an answer for most of you. anyway, it could help.
So I call this in onCreateView() in fragment_init().
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
And I then call this in onCreateView() in the next fragment:
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
:-/
Any other idea?
Use commitAllowingStateLoss() instead of commit()
if (savedInstanceState == null) {
FragmentTransaction fragmentTransaction =getSupportFragmentManager().beginTransaction();
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.replace(R.id.frame_container, new Fragment_init(site)).commitAllowingStateLoss();
}
You should see this blog about on how to avoid that exception: http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
So I solved my problem using the wonderfull message handler implementation explained here:
How to handle Handler messages when activity/fragment is paused
Thx to Akagami which pointed me on the post.
Regards,
This is a little XML animation that I'm trying to get to go off while the app is getting JSON from the server. It takes about 2 seconds to fetch all the data so I'm trying to show a little loading animation.
The problem I am having is that the images do not change until everything is done and onPostExecute() goes off.
Do I need to pass a view into the AsyncTask or is it something else?
One last thing after this AsyncTask completes. It runs smooth if you run it again.
XML
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="#drawable/loadingtext1" android:duration="100" />
<item android:drawable="#drawable/loadingtext2" android:duration="100" />
<item android:drawable="#drawable/loadingtext3" android:duration="100" />
<item android:drawable="#drawable/loadingtext4" android:duration="100" />
</animation-list>
Code
private class LOGMEIN extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
CRY.CInit(DI, DU, DP);
publishProgress(0);
while(data != "whatineed"){
try {
Thread.sleep(450);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
completecheck = 1;
return "complete";
}
#Override
protected void onPreExecute() {
LOADINGTEXT.setBackgroundResource(R.drawable.animation);
AnimationDrawable LT = (AnimationDrawable) LOADINGTEXT.getBackground();
LT.start();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result.contentEquals("complete") == true) {
domorework();
} else {
finish();
}
}
}
Have you set onPreExecute() within the AsyncTask?
protected void onPreExecute() {
//show your animated loader here...
progress.show();
}
I use this in onCreate():
Initialize: public ProgressDialog progress;
progress = new ProgressDialog(this);
progress.setCancelable(true);
progress.setInverseBackgroundForced(false);
progress.setCanceledOnTouchOutside(true);
progress.setMessage("Loading.....");
I don't know if this is the only problem but you are comparing your Strings wrong in your loop.
while (data != "whatineed")
should be
while (!data.equals("whatineed"))
or even better would be
while (!"whatineed".equals(data))
to compare the values instead of the object reference
Firs of all thanks for reading this.
I'm having trouble updating the progress from my custom ProgressBar through an AsyncTask inner class. I'm using 9patch for the background and progress drawables. It just don't update. It stays there all filled like it was in the maxed value, I'm using the onProgressUpdate() to call the invalidate() and update the UI thread.
Here's what it looks like now, it goes visible and just stays there all filled up: http://imageshack.us/photo/my-images/651/mobicashprogressbar.png/
The progressbar should only be
visible after the user concludes the
form.
There's another inner AsyncTask handling the send SMS button that connects with an Web Service.
HERES THE CODE:
public void setTimerProgress(int progress){
progressBar.setProgress(progress);
}
public void updateProgress(){
progressBar.invalidate();
}
public void showProgress(){
progressBar.setVisibility(View.VISIBLE);
}
//Classe auxiliar para controle da progress bar
private class TimerProgress extends AsyncTask<Void, Void, Void>{
private int start;
private final int OTP_TIMEOUT = 900000;
#Override
protected void onPreExecute() {
super.onPreExecute();
showProgress();
start = (int) System.currentTimeMillis();
}
#Override
protected Void doInBackground(Void... param) {
int timer = (int) System.currentTimeMillis() - start;
while (timer <= OTP_TIMEOUT){
setTimerProgress(timer);
timer = (int) System.currentTimeMillis() - start;
publishProgress();
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
updateProgress();
}
}
HERE'S XML:
<ProgressBar
style="#android:style/Widget.ProgressBar.Horizontal"
android:layout_gravity="center_horizontal"
android:visibility="invisible"
android:id="#+id/progress_bar_timer"
android:max="900000"
android:progress="3000"
android:progressDrawable="#drawable/progress_bar"
android:background="#drawable/progress_background"
android:layout_width="fill_parent"
android:layout_height="25dip"
android:layout_marginRight="73sp"
android:layout_marginLeft="70sp">
</ProgressBar>
HERE'S ONE PLACE WHERE I CALL IT
#Override
public void onClick(View v) {
if (v.getId() == R.id.refresh_otp) {
saveParametersForOTP();
if (edtIniPin.getText().length() == pinLengthInt) {
try {
disableEditText(edtIniPin);
disableEditText(edtValue);
edtOTP.setText(Facade.getInstance().nextOTP(Facade.getInstance().getPin(), Facade.getInstance().getValue()));
//Inicia o timer da progressbar
new TimerProgress().execute();
Help? :D
UPDATE:
For test purpuses I've set the OTP_TIMEOUT to 50000, made the following changes to the code and removed the 9patch drawables properties so it would use the native drawables for the bar. It works, however, when I use the images to customize the bar it appears the same old problem is happening. It is static, all filled up like before.
private final int OTP_TIMEOUT = 50000;
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.i("PROGRESS", "Chegou no PreExecute!");
showProgress();
ENABLE_REFRESH = false;
start = (int) System.currentTimeMillis();
}
#Override
protected Void doInBackground(Void... param) {
int timer = (int) System.currentTimeMillis() - start;
while (timer <= OTP_TIMEOUT){
Log.i("PROGRESS", "Chegou no while!");
setTimerProgress((int)timer);
timer = (int) System.currentTimeMillis() - start;
publishProgress();
if (timer >= OTP_TIMEOUT) {
ENABLE_REFRESH = true;
}
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
Log.i("PROGRESS", "Chegou no Progress Update!");
updateProgress();
}
You need to add a layer-list resource and configure your ProgressBar to use it.
Here an example that I use. Note that in progress_bar.xml progress_bar_progress and progress_bar_background are nine-patch images.
progress_bar.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background" android:drawable="#drawable/progress_bar_background" />
<item android:id="#android:id/progress" >
<clip android:drawable="#drawable/progress_bar_progress" />
</item>
</layer-list>list>
layout snippet:
<ProgressBar
android:layout_width="fill_parent"
android:layout_height="30dp"
android:max="100"
android:progress="50"
android:progressDrawable="#drawable/progress_bar"
android:indeterminateOnly="false" />