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,
Related
Instead of getting checkbox like this(i am getting it only few times randomly when moving from on fragment to another).
I am getting like this(checkbox is still true but only tik mark is missing randomly)
I am using onSaveInstanceState and onViewStateRestored. The problem is the checkbox tik mark only disappears and comes back few times but the state of checkbox is still selected i see blue color around all the selected check boxes that selected color doesn't go away only the tik mark goes away and comes back randomly.
Layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:drawableLeft="#drawable/ic_tv"
android:text="TV"
android:theme="#style/CheckBoxTheme"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Tv" />
</android.support.constraint.ConstraintLayout>
</ScrollView>
My Fragment:
public class StepFragmentTwo extends Fragment implements BlockingStep {
private static final String CLICKS_KEY = "clicks";
private static final String TAG = "ADERVERTISMENT";
private int i = 0;
FragmentManager fm = getFragmentManager();
CheckBox c;
Boolean tv = false ;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(getLayoutResId(), container, false);
c = (CheckBox)v.findViewById(R.id.checkBox);
//initialize your UI
return v;
}
protected int getLayoutResId() {
return getArguments().getInt(String.valueOf(R.layout.step2));
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(CLICKS_KEY, i);
super.onSaveInstanceState(outState);
if(outState!=null) {
outState.putBoolean("c", c.isChecked());
}
}
#Override
public void onViewStateRestored(#Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
if(savedInstanceState!=null) {
tv = savedInstanceState.getBoolean("c");
}
}
#Override
public void onResume() {
super.onResume();
c.setChecked(tv);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
public void onNextClicked(final StepperLayout.OnNextClickedCallback callback) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (c.isChecked()) {
tv = true;
}
SharedPreferences shared = getActivity().getSharedPreferences("Mypref", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = shared.edit();
editor.putBoolean("tv", tv);
editor.apply(); // This line is IMPORTANT !!!
callback.goToNextStep();
}
}, 200L);
}
#Override
#UiThread
public void onCompleteClicked(final StepperLayout.OnCompleteClickedCallback callback) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
callback.complete();
}
}, 2000L);
}
public static StepFragmentTwo newInstance(#LayoutRes int layoutResId) {
Bundle args = new Bundle();
args.putInt(String.valueOf(R.layout.step2), layoutResId);
StepFragmentTwo fragment = new StepFragmentTwo();
fragment.setArguments(args);
return fragment;
}
#Override
public VerificationError verifyStep() {
//return null if the user can go to the next step, create a new VerificationError instance otherwise
return null;
}
#Override
public void onSelected() {
//update UI when selected
}
#Override
public void onError(#NonNull VerificationError error) {
//handle error inside of the fragment, e.g. show error on EditText
}
public void onBackClicked(StepperLayout.OnBackClickedCallback callback) {
//Toast.makeText(this.getContext(), "Your custom back action. Here you should cancel currently running operations", Toast.LENGTH_SHORT).show();
callback.goToPrevStep();
}
}
In short you can do,
#Override
public void onResume() {
super.onResume();
SharedPreferences shared = getActivity().getSharedPreferences("Mypref", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = shared.edit();
tv = editor.getBoolean("tv", tv);
c.setChecked(tv);
}
I am building my first android app using WiFi Direct to transfer
text, image, and media files to peers.I am using a RecyclerView
and a Fragment. I hope to show peers's list on a framelayout
(a simple textview) and then click the views to form a group
to send files. I am stuck at the first stage of making the list shown
on the parent's view. I would appreciate your help on what I did wrong.
I am just a beginner. Any advice or resources would be welcome even besides the pending problem. The followings are three classes and two xmls I've made fumbling around many sources and Android Developer's guide.
public class MainActivity extends FragmentActivity {
public static String TAG="test";
IntentFilter mIntentFilter;
WifiP2pManager.Channel mChannel;
WifiP2pManager mManager;
BroadcastReceiver mReceiver;
public static boolean setIsWifiP2pEnable;
Button open, connect, file, image, media;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
open = (Button) findViewById(R.id.wifi_open);
connect = (Button) findViewById(R.id.connect);
file = (Button) findViewById(R.id.file);
image = (Button) findViewById(R.id.gallery);
media = (Button) findViewById(R.id.media);
open.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
startActivity(intent);
}
});
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
checkWiFi();
connect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Log.d (TAG, "search start");
}
#Override
public void onFailure(int reasonCode) {
Log.d (TAG, "search failed");
}
});
}
});
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
if (fragment == null) {
fragment = new DeviceFragment();
fm.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
Log.d (TAG, "fragment_activated");
}
}
#Override
protected void onResume () {
super.onResume();
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
registerReceiver(mReceiver, mIntentFilter);
}
#Override
protected void onPause () {
super.onPause();
unregisterReceiver(mReceiver);
}
public void checkWiFi(){
if(setIsWifiP2pEnable==true){
Toast.makeText(MainActivity.this, "WiFi Direct connected", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Open WiFi Direct in settings", Toast.LENGTH_LONG).show();
}
}
}
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
public static WifiP2pManager mManager;
public static WifiP2pManager.Channel mChannel;
private MainActivity mActivity;
public static List<WifiP2pDevice> peers = new ArrayList<>();
public WiFiDirectBroadcastReceiver(WifiP2pManager manager, WifiP2pManager.Channel channel,
MainActivity activity) {
super();
this.mManager = manager;
this.mChannel = channel;
this.mActivity = activity;
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
int state = intent.getIntExtra(mManager.EXTRA_WIFI_STATE, -1);
if (state==mManager.WIFI_P2P_STATE_ENABLED){
Log.d (MainActivity.TAG, "WiFi_enabled");
mActivity.setIsWifiP2pEnable=true;
mActivity.checkWiFi();
} else {
Log.d (MainActivity.TAG, "WiFi_failed");
mActivity.setIsWifiP2pEnable=false;
mActivity.checkWiFi();
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
if (mManager != null) mManager.requestPeers(mChannel, new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
Log.d (MainActivity.TAG, "peers_found");
peers.clear();
peers.addAll(peerList.getDeviceList());
if(peers.size() ==0){
Log.d (MainActivity.TAG, "No_Peers_found");
return;
}
}
});
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
// Respond to new connection or disconnections
if (mManager==null) {
return;
}
NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
if (networkInfo.isConnected()){
mManager.requestConnectionInfo(mChannel, new WifiP2pManager.ConnectionInfoListener() {
#Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
InetAddress groupOwnerAddress = info.groupOwnerAddress;
String s=groupOwnerAddress.getHostAddress();
if (info.groupFormed && info.isGroupOwner) {
} else if (info.groupFormed) {
}
}
});
}
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
}
}
}
public class DeviceFragment extends Fragment {
private RecyclerView mDeviceRecyclerView;
private DeviceAdapter mAdapter;
private List<WifiP2pDevice> mDevices;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_device_list, container,false);
mDeviceRecyclerView = (RecyclerView) view
.findViewById(R.id.device_recycler_view);
mDeviceRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
private void updateUI(){
mDevices = WiFiDirectBroadcastReceiver.peers;
mAdapter = new DeviceAdapter(mDevices);
mDeviceRecyclerView.setAdapter(mAdapter);
Log.d (MainActivity.TAG, "adapter_connected");
}
private class DeviceHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView mTitleTextView;
public DeviceHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
mTitleTextView = (TextView) itemView;
Log.d(MainActivity.TAG, "Item_Click_try");
}
#Override
public void onClick(View v) {
Toast.makeText(getActivity(),"Click Succeeded", Toast.LENGTH_LONG).show();
int i = (int) v.getTag();
WifiP2pDevice device = mDevices.get(i);
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
WiFiDirectBroadcastReceiver.mManager.connect(WiFiDirectBroadcastReceiver.mChannel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Log.d (MainActivity.TAG, "Click_Success!!");
}
#Override
public void onFailure(int reason) {
Log.d (MainActivity.TAG, "Click_Failed!!");
}
});
}
}
private class DeviceAdapter extends RecyclerView.Adapter<DeviceHolder>{
private List<WifiP2pDevice> Devices;
public DeviceAdapter(List<WifiP2pDevice> devices){
Devices=devices;
Log.d (MainActivity.TAG, "device_list");
}
#Override
public DeviceHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View view=layoutInflater
.inflate(android.R.layout.simple_list_item_1, parent, false);
Log.d (MainActivity.TAG, "simple_list");
return new DeviceHolder(view);
}
#Override
public void onBindViewHolder(DeviceHolder holder, int position) {
WifiP2pDevice device = Devices.get(position);
holder.mTitleTextView.setTag(position);
holder.mTitleTextView.setText(device.deviceName);
Log.d (MainActivity.TAG, "Device_bound");
}
#Override
public int getItemCount() {
return mDevices.size();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content"
tools:context="com.moon.android.wifidirectproject_moon.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="#+id/wifi_open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="WiFi_Direct" />
<Button
android:id="#+id/connect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Connect" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="#+id/file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="file" />
<Button
android:id="#+id/gallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="gallery" />
<Button
android:id="#+id/media"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="media" />
</LinearLayout>
The Other Layout:
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/device_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
I think I have made some (not complete) progress on my question. I suspected that the ArrayList information is not properly delivered to my fragment class. So I wrote the following code in OnCreate method in MainActivity:
DeviceFragment df = new DeviceFragment();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("bundle",WiFiDirectBroadcastReceiver.peers);
df.setArguments(bundle);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
if (fragment == null) {
fragment = df;
fm.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
Log.d (TAG, "fragment_activated");
}
I put the following code in my fragment class:
mDevices = getArguments().getParcelableArrayList("bundle");
and revised Adapter class as follows:
public DeviceAdapter(List<WifiP2pDevice> devices){
Devices=devices;
notifyDataSetChanged();
Log.d (MainActivity.TAG, "device_list");
}
It worked. But I met with one more problem. The textviews on screen are refreshed only when I turned off and on again (not powered on/off). So, I want to make a "refresh button" in MainActivity so that I can refresh the list like when turning on/off. But I have no idea how I can refresh the RecyclerView's fragment in MainActivity. I think I should work on fragmentManager and transaction. Could anybody help me deal with this issue?
I am trying to implement "Swipe to load more" method in my application but I got that error when I swipe down in the first time. This is what it showed in the console:
E/SwipeRefreshLayout: Got ACTION_MOVE event but don't have an active
pointer id. E/SwipeRefreshLayout: Got ACTION_MOVE event but don't have
an active pointer id. E/SwipeRefreshLayout: Got ACTION_MOVE event but
don't have an active pointer id. E/SwipeRefreshLayout: Got ACTION_MOVE
event but don't have an active pointer id.
This is my layout code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="training.com.chatgcmapplication.ChatActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeLayout"
android:layout_width="match_parent"
android:layout_height="380dp">
<ListView
android:id="#+id/listMessage"
android:layout_width="match_parent"
android:layout_height="380dp"
android:layout_alignParentLeft="false"
android:layout_alignParentTop="false"
android:divider="#null"
android:listSelector="#android:color/transparent"
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll" />
</android.support.v4.widget.SwipeRefreshLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1">
<EditText
android:id="#+id/txt_chat"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.92"
android:inputType="text" />
<Button
android:id="#+id/btn_send"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="30dp"
android:text="#string/btn_send" />
</LinearLayout>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
And when I swipe in the second time: it load double data.
This is ChatActivity, what implement that method:
public class ChatActivity extends AppCompatActivity implements View.OnClickListener, SwipeRefreshLayout.OnRefreshListener {
private static EditText txt_chat;
private String registId;
private String chatTitle;
private MessageSender mgsSender;
private int userId;
private DatabaseHelper databaseHelper;
private TimeUtil timeUtil;
private MessageAdapter messageAdapter;
private int offsetNumber = 5;
private SwipeRefreshLayout swipeRefreshLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
Button btn_send = (Button) findViewById(R.id.btn_send);
txt_chat = (EditText) findViewById(R.id.txt_chat);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeLayout);
swipeRefreshLayout.setOnRefreshListener(this);
ListView lv_message = (ListView) findViewById(R.id.listMessage);
timeUtil = new TimeUtil();
databaseHelper = DatabaseHelper.getInstance(getApplicationContext());
btn_send.setOnClickListener(this);
Bundle bundle = getIntent().getExtras();
chatTitle = bundle.getString("titleName");
if (getIntent().getBundleExtra("INFO") != null) {
chatTitle = getIntent().getBundleExtra("INFO").getString("name");
this.setTitle(chatTitle);
} else {
this.setTitle(chatTitle);
}
registId = bundle.getString("regId");
userId = databaseHelper.getUser(chatTitle).getUserId();
List<Message> messages = databaseHelper.getLastTenMessages(AppConfig.USER_ID, databaseHelper.getUser(chatTitle).getUserId(), 0);
messageAdapter = new MessageAdapter(getApplicationContext(), R.layout.chat_item, (ArrayList<Message>) messages);
LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, new IntentFilter("Msg"));
if (messages.size() > 0) lv_message.setAdapter(messageAdapter);
}
private BroadcastReceiver onNotice = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
try {
Message messageObj = new Message();
messageObj.setMessage(message);
messageObj.setUserId(userId);
messageObj.setSender_id(AppConfig.USER_ID);
messageObj.setExpiresTime(timeUtil.formatDateTime(timeUtil.getCurrentTime()));
messageAdapter.add(messageObj);
} catch (ParseException e) {
e.printStackTrace();
}
messageAdapter.notifyDataSetChanged();
}
};
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
#Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
super.onDestroy();
}
private static MessageSenderContent createMegContent(String regId, String title) {
String message = txt_chat.getText().toString();
MessageSenderContent mgsContent = new MessageSenderContent();
mgsContent.addRegId(regId);
mgsContent.createData(title, message);
return mgsContent;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send:
String message = txt_chat.getText().toString();
databaseHelper = DatabaseHelper.getInstance(getApplicationContext());
mgsSender = new MessageSender();
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
MessageSenderContent mgsContent = createMegContent(registId, AppConfig.USER_NAME);
mgsSender.sendPost(mgsContent);
return null;
}
}.execute();
databaseHelper.addMessage(message, timeUtil.getCurrentTime(), userId, AppConfig.USER_ID);
txt_chat.setText("");
try {
Message messageObj = new Message();
messageObj.setMessage(message);
messageObj.setUserId(AppConfig.USER_ID);
messageObj.setSender_id(userId);
messageObj.setExpiresTime(timeUtil.formatDateTime(timeUtil.getCurrentTime()));
messageAdapter.add(messageObj);
} catch (ParseException e) {
e.printStackTrace();
}
messageAdapter.notifyDataSetChanged();
break;
}
}
#Override
public void onRefresh() {
swipeRefreshLayout.setRefreshing(true);
List<Message> messages = databaseHelper.getLastTenMessages(AppConfig.USER_ID, databaseHelper.getUser(chatTitle).getUserId(), offsetNumber);
messageAdapter.insertToTheFirst(messages);
messageAdapter.notifyDataSetChanged();
offsetNumber += 5;
Log.i("Offset number", offsetNumber + "");
swipeRefreshLayout.setRefreshing(false);
}
}
UPDATE ISSUE's REASON
I found the reason of that issue. It due to I force the listview scroll to the bottom when it init with this code :
android:stackFromBottom="true"
I replace that code with this but still have same issue:
lv_message.post(new Runnable() {
#Override
public void run() {
lv_message.setSelection(lv_message.getCount() -1);
}
});
I think the problem is , You are trying to show , dismiss and refresh swipeRefreshLayout inside the same method i.e onRefresh().
Make seperate methods for showing and dismissing dialog and invoke them from the place where they are required as I have done below:
#Override
public void onRefresh() {
// refresh code here.
}
#Override
public void showDialog() {
swipeRef.post(new Runnable() {
#Override
public void run() {
if(swipeRef != null)
swipeRef.setRefreshing(true);
}
});
}
#Override
public void dismissDialog() {
if(swipeRef!=null && swipeRef.isShown() )
swipeRef.setRefreshing(false);
}
I'm new to android programming. I want to create a custom progress dialog with some textview and button and showing the progress with two progressBar and updating them while sending the files from Asynctask, Also I want it works with minimum API 10. google doc recommend me to use DialogFragment and i do not have any idea how to update the progress bars and textviews that are in that custom layout of my fragmentDialog, when I try to reference a textview or progress bar it throw null exeption
Here is my code
public static class FireMissilesDialogFragment extends DialogFragment {
public FireMissilesDialogFragment(){
}
public static FireMissilesDialogFragment newInstance(String title) {
FireMissilesDialogFragment frag = new FireMissilesDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = this.getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
View view = inflater.inflate(R.layout.custom_progress, null);
ProgressBar pbCurrent = (ProgressBar) view.findViewById(R.id.current);
builder.setView(view);
builder.setMessage("Fire Missiles")
.setPositiveButton("Fire", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// FIRE ZE MISSILES!
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
I got a nullExeption here in my main activity when try to reference a view
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button frag = (Button) findViewById(R.id.frag);
frag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FireMissilesDialogFragment fragment = FireMissilesDialogFragment.newInstance("hi") ;
fragment.getActivity().findViewById(R.id.current);// nullExeption here
// downloadAsync as = new downloadAsync();
// as.execute();
}
});
I didn't see much question and example about that, did I go all the way wrong and should pick another way to achieve my point??!!
Edit :
I'm trying to create something like this
thanks in advance
I can not do a full explanation but I can leave an example and then hopefully you can figure out a way to incorporate the things you need.
The DialogFragment with an AsyncTask and a Progress bar:
public class LoadHydrantsToMapTaskFragment extends DialogFragment {
public static final String TAG = LoadHydrantsToMapTaskFragment.class
.getSimpleName();
public interface LoadHydrantsToMapTaskCallback {
void onPreExecute(int maxProgress);
void onProgressUpdate(int progress);
void onCancelled();
void onPostExecute();
}
private LoadHydrantsToMapTask mTask;
// private ProgressBar mProgressBar;
private List<HydrantHolder> mHydrants;
private GoogleMap map;
public static LoadHydrantsToMapTaskFragment newInstance(
List<HydrantHolder> hydrants, GoogleMap map) {
LoadHydrantsToMapTaskFragment taskFragment = new LoadHydrantsToMapTaskFragment();
taskFragment.mHydrants = hydrants;
taskFragment.map = map;
return taskFragment;
}
#Override public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_progress_task, container);
mProgressBar = (ProgressBar) view.findViewById(R.id.progressBar);
mProgressBar.setProgress(0);
mProgressBar.setMax(mHydrants.size());
getDialog().setTitle(getActivity().getString(R.string.adding_hydrants));
// This dialog can't be canceled by pressing the back key.
getDialog().setCancelable(false);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
/**
* This method will only be called once when the retained Fragment is first
* created.
*/
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(SherlockDialogFragment.STYLE_NORMAL, R.style.TuriosDialog);
// Retain this fragment across configuration changes.
setRetainInstance(true);
mTask = new LoadHydrantsToMapTask(mHydrants);
mTask.setCallback(new LoadHydrantsToMapTaskCallback() {
#Override public void onPreExecute(int maxProgress) {
}
#Override public void onProgressUpdate(int progress) {
mProgressBar.setProgress(progress);
}
#Override public void onPostExecute() {
if (isResumed())
dismiss();
mTask = null;
}
#Override public void onCancelled() {
if (isResumed())
dismiss();
mTask = null;
}
});
mTask.execute();
}
#Override public void onResume() {
super.onResume();
// This is a little hacky, but we will see if the task has finished
// while we weren't
// in this activity, and then we can dismiss ourselves.
if (mTask == null)
dismiss();
}
#Override public void onDetach() {
super.onDetach();
}
// This is to work around what is apparently a bug. If you don't have it
// here the dialog will be dismissed on rotation, so tell it not to dismiss.
#Override public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
// Also when we are dismissed we need to cancel the task.
#Override public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
// If true, the thread is interrupted immediately, which may do bad
// things.
// If false, it guarantees a result is never returned (onPostExecute()
// isn't called)
// but you have to repeatedly call isCancelled() in your
// doInBackground()
// function to check if it should exit. For some tasks that might not be
// feasible.
if (mTask != null)
mTask.cancel(false);
}
private class LoadHydrantsToMapTask extends
AsyncTask<Void, Integer, List<MarkerOptions>> {
// Before running code in separate thread
List<HydrantHolder> mHydrants;
LoadHydrantsToMapTaskCallback mLoadHydrantsToMapTaskCallback;
public LoadHydrantsToMapTask(List<HydrantHolder> hydrants) {
this.mHydrants = hydrants;
}
public void setCallback(
LoadHydrantsToMapTaskCallback loadHydrantsToMapTaskCallback) {
this.mLoadHydrantsToMapTaskCallback = loadHydrantsToMapTaskCallback;
}
#Override protected void onPreExecute() {
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onPreExecute(mHydrants.size());
}
}
// The code to be executed in a background thread.
#Override protected List<MarkerOptions> doInBackground(Void... arg) {
List<MarkerOptions> markers = new ArrayList<MarkerOptions>();
for (HydrantHolder hydrant : mHydrants) {
final String hydrant_type = hydrant.getHydrantType();
final String hydrant_icon_path = hydrant.getIconPath();
double latitude = hydrant.getLatitude();
double longitude = hydrant.getLongitude();
final LatLng position = new LatLng(latitude, longitude);
final String address = hydrant.getAddress();
final String addressNumber = hydrant.getAddressNumber();
final String addressremark = hydrant.getAddressRemark();
final String remark = hydrant.getRemark();
// Log.d(TAG, hydrant.toString());
BitmapDescriptor icon = BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_RED);
if (!hydrant_icon_path.isEmpty()) {
File iconfile = new File(hydrant_icon_path);
if (iconfile.exists()) {
BitmapDescriptor loaded_icon = BitmapDescriptorFactory
.fromPath(hydrant_icon_path);
if (loaded_icon != null) {
icon = loaded_icon;
} else {
Log.e(TAG, "loaded_icon was null");
}
} else {
Log.e(TAG, "iconfile did not exist: "
+ hydrant_icon_path);
}
} else {
Log.e(TAG, "iconpath was empty on hydrant type: "
+ hydrant_type);
}
StringBuffer snippet = new StringBuffer();
if (!address.isEmpty())
snippet.append("\n" + address + " " + addressNumber);
if (addressremark.isEmpty())
snippet.append("\n" + addressremark);
if (!remark.isEmpty())
snippet.append("\n" + remark);
markers.add(new MarkerOptions().position(position)
.title(hydrant_type).snippet(snippet.toString())
.icon(icon));
publishProgress(markers.size());
}
return markers;
}
// Update the progress
#Override protected void onProgressUpdate(Integer... values) {
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onProgressUpdate(values[0]);
}
}
#Override protected void onCancelled() {
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onCancelled();
}
}
// after executing the code in the thread
#Override protected void onPostExecute(List<MarkerOptions> markers) {
for (MarkerOptions marker : markers) {
if (marker != null && map != null)
map.addMarker(marker);
}
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onPostExecute();
}
}
}
}
My dialog_progress_task layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:maxHeight="10dip"
android:minHeight="10dip"
android:progress="0"
android:progressDrawable="#drawable/progress_orange" />
</LinearLayout>
And finally the code I use to add it:
#Override public void loadHydrantsToMap(List<HydrantHolder> hydrants,
GoogleMap map) {
LoadHydrantsToMapTaskFragment loadHydrantsFragment;
if (fm != null) {
FragmentTransaction ft = fm.beginTransaction();
loadHydrantsFragment = (LoadHydrantsToMapTaskFragment) fm
.findFragmentByTag(LoadHydrantsToMapTaskFragment.TAG);
if (loadHydrantsFragment != null) {
Log.i("Attatching LoadHydrantsToMapTaskFragment");
ft.attach(loadHydrantsFragment);
} else {
loadHydrantsFragment = LoadHydrantsToMapTaskFragment
.newInstance(hydrants, map);
Log.i("Adding new LoadHydrantsToMapTaskFragment");
ft.add(loadHydrantsFragment, LoadHydrantsToMapTaskFragment.TAG);
}
ft.commit();
}
}
First of all, I am relatively new to android programming.
I am creating a ViewPager application with two Fragments. One of the Fragments requests data from a server and return a result to the main FragmentActivity. My problem is that this request to the server can take sometime, and I have been trying to get a ProgressDialog to appear with AsyncTask while the user waits for the data to be retrieved. Once I create the background thread to retrieve the data, I successfully execute some code in the onPostExecute() method and set some variables. However, the return statement that sends information back to the FragmentActivity is being executed before the background thread actually ends. I can't seem to figure out a way for the main thread to wait on the background thread. Using Asyctask's get() method results in the ProgressDialog from appearing. I have looked through a lot of posts in here, but can't seem to find an answer.
Anything helps.
Code below:
SplashScreen.java
public class SplashScreen extends FragmentActivity {
MainMenu mainMenu;
MapScreen mapScreen;
PagerAdapter pagerAdapter;
ViewPager viewPager;
List<LatLng> geoPoints;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_splash_screen);
context = this;
initializePaging();
}
private void initializePaging()
{
mainMenu = new MainMenu();
mapScreen = new MapScreen();
pagerAdapter = new PagerAdapter(getSupportFragmentManager());
pagerAdapter.addFragment(mainMenu);
pagerAdapter.addFragment(mapScreen);
viewPager = (ViewPager) super.findViewById(R.id.viewPager);
viewPager.setAdapter(pagerAdapter);
viewPager.setOffscreenPageLimit(2);
viewPager.setCurrentItem(0);
viewPager.setOnPageChangeListener(new OnPageChangeListener()
{
#Override
public void onPageScrollStateChanged(int postion){}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2){}
#Override
public void onPageSelected(int position)
{
switch(position){
case 0: findViewById(R.id.first_tab).setVisibility(View.VISIBLE);
findViewById(R.id.second_tab).setVisibility(View.INVISIBLE);
break;
case 1: findViewById(R.id.first_tab).setVisibility(View.INVISIBLE);
findViewById(R.id.second_tab).setVisibility(View.VISIBLE);
break;
}
}
});
}
//Called from onClick in main_mainu.xml
public void getDirections(View view)
{
InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
try
{
geoPoints = mainMenu.getDirections(context);
mapScreen.plotPoints(geoPoints);
}
catch(Exception e)
{
Toast.makeText(getApplicationContext(), "Error! Invalid address entered.", Toast.LENGTH_LONG).show();
mainMenu.clear();
}
}
}
MainMenu.java
public class MainMenu extends Fragment {
String testString;
int testInt;
TextView testTV;
private TextView tvDisplay;
private EditText departure;
private EditText destination;
private Geocoder geocoder;
private List<Address> departAddress;
private List<Address> destinationAddress;
private List<LatLng> geoPoints;
private String departString;
private String destinationString;
private Address departLocation;
private Address destinationLocation;
private LatLng departurePoint;
private LatLng destinationPoint;
private Context contextMain;
private GetData task;
public MainMenu()
{
super();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View root = (View) inflater.inflate(R.layout.main_menu, null);
geoPoints = new ArrayList<LatLng>(2);
return root;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
departure = (EditText) getView().findViewById(R.id.depart_field);
destination = (EditText) getView().findViewById(R.id.destination_field);
tvDisplay = (TextView) getView().findViewById(R.id.textView1);
}
public List<LatLng> getDirections(Context context)
{
contextMain = context;
geocoder = new Geocoder(getActivity());
departString = departure.getText().toString();
destinationString = destination.getText().toString();
try
{
task = new GetData(new Callback(){
public void run(Object result)
{
//return geoPoints;
}
});
task.execute((Void[])null);
}catch(Exception e)
{
e.printStackTrace();
}
return geoPoints;
}
public void clear()
{
departure.setText("");
destination.setText("");
tvDisplay.setText("Enter departure point, and destination point");
}
private class GetData extends AsyncTask<Void, Void, List<List<Address>>>
{
Callback callback;
private ProgressDialog processing;
public GetData(Callback callback)
{
this.callback = callback;
}
#Override
protected void onPreExecute()
{
processing = new ProgressDialog(contextMain);
processing.setTitle("Processing...");
processing.setMessage("Please wait.");
processing.setCancelable(false);
processing.setIndeterminate(true);
processing.show();
}
#Override
protected List<List<Address>> doInBackground(Void...arg0)
{
List<List<Address>> list = new ArrayList<List<Address>>(2);
try
{
departAddress = geocoder.getFromLocationName(departString, 5, 37.357059, -123.035889, 38.414862, -121.723022);
destinationAddress = geocoder.getFromLocationName(destinationString, 5, 37.357059, -123.035889, 38.414862, -121.723022);
list.add(departAddress);
list.add(destinationAddress);
}catch(IOException e)
{
e.printStackTrace();
}
return list;
}
#Override
protected void onPostExecute(List<List<Address>> list)
{
departLocation = list.get(0).get(0);
destinationLocation = list.get(1).get(0);
departurePoint = new LatLng(departLocation.getLatitude(), departLocation.getLongitude());
destinationPoint = new LatLng(destinationLocation.getLatitude(), destinationLocation.getLongitude());
if(geoPoints.size() >= 2)
{
geoPoints.clear();
}
geoPoints.add(departurePoint);
geoPoints.add(destinationPoint);
callback.run(list);
processing.dismiss();
}
}
}
#Override
protected Object doInBackground(Void...arg0)
{
Object result = null;
try
{
departAddress = geocoder.getFromLocationName(departString, 5, 37.357059, -123.035889, 38.414862, -121.723022);
destinationAddress = geocoder.getFromLocationName(destinationString, 5, 37.357059, -123.035889, 38.414862, -121.723022);
}catch(IOException e)
{
e.printStackTrace();
}
return result;
}
You never set the value of result...