I’ve got a MainActivity which has two tabs on ActionBar. My main layout on that activity is an empty FrameLayout. The first tab contains a ProgressBar, the second has Button that starts downloading files. Here’s SettingsTab:
public class SettingsTab extends Fragment {
private Button downloadButton;
private ImagesTab imagesTab;
private static String fileDir = "sdcard/AndroidCourse/";
public void downloadImages(String url,int limit,String imageExtension)
{
try {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()
.build());
Document doc = Jsoup.connect(url).get();
StringBuilder sb = new StringBuilder("img[src$=.");
sb.append(imageExtension);
sb.append("]");
Elements images = doc.select(sb.toString());
ArrayList<String> urls = new ArrayList<String>();
for(Element image : images) {
if(urls.size() == limit) {
break;
}
urls.add(image.attr("src"));
}
Log.e("urls", String.valueOf(urls.size()));
imagesTab.downloadStarted(urls);
} catch (IOException e) {
Log.e("SettingsTab", e.getMessage());
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.settings_tab, null);
downloadButton = (Button) view.findViewById(R.id.startButton);
imagesTab = new ImagesTab();
downloadButton.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
downloadImages("http://www.google.com",5,"jpg");
}
});
return view;
}
}
and ImagesTab:
public class ImagesTab extends Fragment {
ProgressBar downloadProgressBar;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.images_tab, null);
downloadProgressBar = (ProgressBar) view.findViewById(R.id.downloadProgressBar);
//downloadProgressBar.setVisibility(View.INVISIBLE);
return view;
}
public void downloadStarted(ArrayList<String> urls)
{
//downloadProgressBar.setVisibility(View.VISIBLE);
Intent intent = new Intent(getActivity(), DownloadService.class);
intent.putExtra("urls", urls);
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
getActivity().startService(intent);
Toast.makeText(getActivity(), "Service started!" + urls.size(), Toast.LENGTH_SHORT).show();
}
private class DownloadReceiver extends ResultReceiver{
public DownloadReceiver(Handler handler) {
super(handler);
}
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == DownloadService.UPDATE_PROGRESS) {
int progress = resultData.getInt("progress");
downloadProgressBar.setProgress(progress);
if (progress == 100) {
downloadProgressBar.setVisibility(View.INVISIBLE);
}
}
}
}
}
When I click the StartDownload Button, the application crashes with the following exception:
11-26 03:55:55.765: E/AndroidRuntime(21200): FATAL EXCEPTION: main
11-26 03:55:55.765: E/AndroidRuntime(21200): java.lang.NullPointerException
11-26 03:55:55.765: E/AndroidRuntime(21200): at android.content.ComponentName.<init>(ComponentName.java:75)
11-26 03:55:55.765: E/AndroidRuntime(21200): at android.content.Intent.<init>(Intent.java:3227)
11-26 03:55:55.765: E/AndroidRuntime(21200): at com.example.lista2.ImagesTab.downloadStarted(ImagesTab.java:32)
11-26 03:55:55.765: E/AndroidRuntime(21200): at com.example.lista2.SettingsTab.downloadImages(SettingsTab.java:55)
11-26 03:55:55.765: E/AndroidRuntime(21200): at com.example.lista2.SettingsTab$1.onClick(SettingsTab.java:72)
Does anyone have an idea how to change the progress of a ProgressBar in on different part of app?
The main problem in your code, and the reason for that
NullPointerExceptionis the line:where you instantiate a new
ImagesTabFragment. The problem is this newFragmentinstance isn’t tied to anActivity(it’s in the “air”) so itsgetActivity()method returnsnull. Thisnullvalue from thegetActivity()method you pass to theIntentthat you build in thedownloadStarted()method which will throw theNulPointerException. Instead of instantiating theImgesTablike you do, you should get a reference to the other fragment which is already(most likely) in the parent activity by using thegetFragmentManager()and searching for the fragment based on its tag.Second, updating the
ProgressBarseems more of a app design problem. For example, why do you have theButtonthat starts the download in a tab and theProgressBarwhich shows the download progress in another tab? Also, you seem to use aServicefor the download, so instead of making the tabs communicating you should really make theServicethat downloads the files and the desired tab fragment(with theProgressBar) communicate. This could be made very simple by making theServiceto a send broadcast at certain download levels and making yourActivity(which holds the two tabs fragments) dynamically registering aBroadcastReceiver. When theServicesends a broadcast(for example at 10%), theActivity‘sBroadcastReceiverwill pick it up(if it’s alive) and then it will update theProgressBarfrom the desiredFragmentif thatFragmentis visible at that moment.