I'm trying to sync a list from the handheld to the wearable. On the phone side, I have a listview and you can add items to it and on the wear side I am just displaying the same list. I'm adding items to /card/id path and adding the array size on /counter. OnDataChanged method does gets called when I add items to the list on phoneside, but when I try to read the items on wearside, it's not working. It gives nullpointer exception when I'm trying to get the connected nodes and therefor I'm not able to read the data. Here's the code and the log snapshot:
Error
04-15 12:41:38.075: E/AndroidRuntime(13791): Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.os.Looper com.google.android.gms.common.api.GoogleApiClient.getLooper()' on a null object reference
Wear side:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDefaultCircleRadius = getResources().getDimension(R.dimen.default_settings_circle_radius);
mSelectedCircleRadius = getResources().getDimension(R.dimen.selected_settings_circle_radius);
cards = new ArrayList<GiftCard>();
new LoadCards().execute();
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
#Override
public void onLayoutInflated(WatchViewStub stub) {
//mTextView = (TextView) stub.findViewById(R.id.count_text);
mListView = (WearableListView) stub.findViewById(R.id.card_list_view);
}
});
mHandler = new Handler();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
// DataItem changed
DataItem item = event.getDataItem();
if (item.getUri().getPath().compareTo(COUNT_PATH) == 0) {
DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
final String counter = dataMap.getString(CardUtil.CARD_COUNT);
new LoadCards().execute();
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(c,"Card count: "+ counter,Toast.LENGTH_LONG).show();
//mTextView.setText("COUNTER FROM DATACHANGE METHOD: " + counter);
}
});
}
else if(item.getUri().getPath().compareTo(CARD_PATH) == 0){
}
} else if (event.getType() == DataEvent.TYPE_DELETED) {
// DataItem deleted
}
}
}
public GiftCard loadCardData(int id){
//Uri uri = getIntent().getData().buildUpon().encodedPath("/card").appendPath(String.valueOf(id)).build();
Uri uri = getUriForDataItem("/counter");
Log.d("URI", uri.getPath());
DataApi.DataItemResult result = Wearable.DataApi.getDataItem(mGoogleApiClient,uri).await();
DataMapItem item = DataMapItem.fromDataItem(result.getDataItem());
Asset cardImageAsset = item.getDataMap().getAsset(CardUtil.CARD_IMAGE);
//Asset barcodeImageAsset = item.getDataMap().getAsset(CardUtil.BARCODE_IMAGE);
String card_type = item.getDataMap().getString(CardUtil.CARD_TYPE);
Bitmap cardImage = BitmapFactory.decodeStream(Wearable.DataApi.getFdForAsset(mGoogleApiClient, cardImageAsset).await().getInputStream());
// Bitmap barcodeImage = BitmapFactory.decodeStream(Wearable.DataApi.getFdForAsset(mGoogleApiClient,barcodeImageAsset).await().getInputStream());
GiftCard card = new GiftCard();
card.setCardImage(cardImage);
card.setCardName(card_type);
card.setCardID(id);
return card;
}
public class LoadCards extends AsyncTask<Void, Void, Boolean> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Boolean doInBackground(Void... arg0) {
// Uri uri = getIntent().getData().buildUpon().encodedPath("/counter").build();
Uri uri = getUriForDataItem("/counter");
Toast.makeText(c,uri.toString(),Toast.LENGTH_LONG).show();
DataApi.DataItemResult result = Wearable.DataApi.getDataItem(mGoogleApiClient,uri).await();
DataMapItem item = DataMapItem.fromDataItem(result.getDataItem());
int card_count = Integer.parseInt(item.getDataMap().getString(CardUtil.CARD_COUNT));
// int card_count = Integer.parseInt(loadCardCounter());
if(card_count <= 0){
Toast.makeText(c,"No cards available to show!",Toast.LENGTH_LONG).show();
} else {
for (int i = 1; i <= card_count; i++) {
GiftCard c = loadCardData(i);
cards.add(c);
}
}
return null;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
//update the card list
mAdapter = new CardListAdapter(c,cards);
mListView.setAdapter(mAdapter);
// mListView.setClickListener();
}
}
private Uri getUriForDataItem(String path) {
String nodeId = getNodeId();
return new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).authority(nodeId).path(path).build();
}
private String getNodeId() {
NodeApi.GetConnectedNodesResult nodesResult = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
List<Node> nodes = nodesResult.getNodes();
if (nodes.size() > 0) {
return nodes.get(0).getId();
} else {
Toast.makeText(c,"NO NODES AVAILABLE",Toast.LENGTH_LONG).show();
}
return null;
}}
From the stacktrace it's pretty obvious that you are trying to use Wearable DataAPI from the thread without Looper - in doInBackground() method I believe. That is why it crashes.
Move this code directly into onDataChanged() method and it should solve the issue.
Related
I keep getting an an error when trying to call WowZa GoCoder SDK's PlayerActivity and I am unable to understand the cause. The error appears when mStreamPlayerView.play(mStreamPlayerConfig, statusCallback) is called. Would really appreciate help on where i am going wrong
vodFragment.java
public class vodFragment extends Fragment {
private int mColumnCount = 1;
ListView videoView;
ArrayList <Vidoes> videoList;
private static String value;
String videoName;
String url = "http://192.168.43.149/twende/channelVOD.php";
public vodFragment() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (getActivity().getActionBar() != null) {
getActivity().getActionBar().setTitle(value);
}
View view = inflater.inflate(R.layout.fragment_vod_list, container, false);
videoView = (ListView) view.findViewById(R.id.listView);
videoList = new ArrayList<Vidoes>();
JSONObject channelInfo = new JSONObject();
try {
channelInfo.put("channelName", value);
channelInfo.put("channelOwner", "dan");
postJSONObject(url,channelInfo);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return view;
}
public static void setChannel(String channel){
value = channel;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
public void postJSONObject(final String myurl, final JSONObject parameters) {
class postJSONObject extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
loadIntoVodView(s);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected String doInBackground(Void... voids) {
HttpURLConnection conn = null;
try {
StringBuffer response = null;
URL url = new URL(myurl);
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setRequestMethod("POST");
OutputStream out = new BufferedOutputStream(conn.getOutputStream());
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
writer.write(parameters.toString());
writer.close();
out.close();
int responseCode = conn.getResponseCode();
System.out.println("responseCode" + responseCode);
switch (responseCode) {
case 200:
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (conn != null) {
try {
conn.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
return null;
}
}
postJSONObject postJSONObject = new postJSONObject();
postJSONObject.execute();
}
private void loadIntoVodView(String json) throws JSONException {
JSONArray jsonArray = new JSONArray(json);
final String[] videos = new String[jsonArray.length()];
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
videos[i] = removeExtension(obj.getString("title"));
Vidoes vidoe = new Vidoes();
vidoe.setTitle(videos[i]);
videoList.add(vidoe);
}
VideoListAdapter adapter = new VideoListAdapter(getActivity(), R.layout.vodparsedata, videoList);
videoView.setAdapter(adapter);
videoView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
videoName = Arrays.asList(videos).get(position);
Intent intent = new Intent(getActivity(), PlayerActivity.class);
String message = videoName+".mp4";
intent.putExtra("videoName", message);
startActivity(intent);
System.out.println("arr: " + Arrays.asList(videos).get(position));
}
});
}
public static String removeExtension(String fileName) {
if (fileName.indexOf(".") > 0) {
return fileName.substring(0, fileName.lastIndexOf("."));
} else {
return fileName;
}
}
}
PlayerActivity.java
public class PlayerActivity extends GoCoderSDKActivityBase {
final private static String TAG = PlayerActivity.class.getSimpleName();
String videoName;
private WOWZPlayerView mStreamPlayerView = null;
private WOWZPlayerConfig mStreamPlayerConfig = new WOWZPlayerConfig();
private MultiStateButton mBtnPlayStream = null;
private MultiStateButton mBtnSettings = null;
private MultiStateButton mBtnMic = null;
private MultiStateButton mBtnScale = null;
private SeekBar mSeekVolume = null;
private ProgressDialog mBufferingDialog = null;
private StatusView mStatusView = null;
private TextView mHelp = null;
private TimerView mTimerView = null;
private ImageButton mStreamMetadata = null;
private boolean mUseHLSPlayback = false;
private WOWZPlayerView.PacketThresholdChangeListener packetChangeListener = null;
private VolumeChangeObserver mVolumeSettingChangeObserver = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stream_player);
mRequiredPermissions = new String[]{};
if (savedInstanceState == null) {
Bundle extras = getIntent().getExtras();
if(extras == null) {
videoName= null;
} else {
videoName= extras.getString("videoName");
}
} else {
videoName= (String) savedInstanceState.getSerializable("videoName");
}
System.out.print(videoName);
mStreamPlayerConfig.setIsPlayback(true);
mStreamPlayerConfig.setHostAddress("192.168.43.149");
mStreamPlayerConfig.setApplicationName("Dark Souls 2 Channel");
mStreamPlayerConfig.setStreamName(videoName);
mStreamPlayerConfig.setPortNumber(1935);
mStreamPlayerView = (WOWZPlayerView) findViewById(R.id.vwStreamPlayer);
mBtnPlayStream = (MultiStateButton) findViewById(R.id.ic_play_stream);
mBtnSettings = (MultiStateButton) findViewById(R.id.ic_settings);
mBtnMic = (MultiStateButton) findViewById(R.id.ic_mic);
mBtnScale = (MultiStateButton) findViewById(R.id.ic_scale);
mTimerView = (TimerView) findViewById(R.id.txtTimer);
mStatusView = (StatusView) findViewById(R.id.statusView);
mStreamMetadata = (ImageButton) findViewById(R.id.imgBtnStreamInfo);
mHelp = (TextView) findViewById(R.id.streamPlayerHelp);
mSeekVolume = (SeekBar) findViewById(R.id.sb_volume);
WOWZStatusCallback statusCallback = new StatusCallback();
mStreamPlayerView.play(mStreamPlayerConfig, statusCallback);
mTimerView.setVisibility(View.GONE);
mStreamPlayerView.play(mStreamPlayerConfig, statusCallback);
if (sGoCoderSDK != null) {
/*
Packet change listener setup
*/
final PlayerActivity activity = this;
packetChangeListener = new WOWZPlayerView.PacketThresholdChangeListener() {
#Override
public void packetsBelowMinimumThreshold(int packetCount) {
WOWZLog.debug("Packets have fallen below threshold "+packetCount+"... ");
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Packets have fallen below threshold ... ", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void packetsAboveMinimumThreshold(int packetCount) {
WOWZLog.debug("Packets have risen above threshold "+packetCount+" ... ");
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Packets have risen above threshold ... ", Toast.LENGTH_SHORT).show();
}
});
}
};
mStreamPlayerView.setShowAllNotificationsWhenBelowThreshold(false);
mStreamPlayerView.setMinimumPacketThreshold(20);
mStreamPlayerView.registerPacketThresholdListener(packetChangeListener);
///// End packet change notification listener
mTimerView.setTimerProvider(new TimerView.TimerProvider() {
#Override
public long getTimecode() {
return mStreamPlayerView.getCurrentTime();
}
#Override
public long getDuration() {
return mStreamPlayerView.getDuration();
}
});
mSeekVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.setVolume(progress);
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// listen for volume changes from device buttons, etc.
mVolumeSettingChangeObserver = new VolumeChangeObserver(this, new Handler());
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mVolumeSettingChangeObserver);
mVolumeSettingChangeObserver.setVolumeChangeListener(new VolumeChangeObserver.VolumeChangeListener() {
#Override
public void onVolumeChanged(int previousLevel, int currentLevel) {
if (mSeekVolume != null)
mSeekVolume.setProgress(currentLevel);
if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.setVolume(currentLevel);
}
}
});
mBtnScale.setState(mStreamPlayerView.getScaleMode() == WOWZMediaConfig.FILL_VIEW);
// The streaming player configuration properties
mStreamPlayerConfig = new WOWZPlayerConfig();
mBufferingDialog = new ProgressDialog(this);
mBufferingDialog.setTitle(R.string.status_buffering);
mBufferingDialog.setMessage(getResources().getString(R.string.msg_please_wait));
mBufferingDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getResources().getString(R.string.button_cancel), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
cancelBuffering(dialogInterface);
}
});
// testing player data event handler.
mStreamPlayerView.registerDataEventListener("onMetaData", new WOWZDataEvent.EventListener(){
#Override
public WOWZDataMap onWZDataEvent(String eventName, WOWZDataMap eventParams) {
String meta = "";
if(eventParams!=null)
meta = eventParams.toString();
WOWZLog.debug("onWZDataEvent -> eventName "+eventName+" = "+meta);
return null;
}
});
// testing player data event handler.
mStreamPlayerView.registerDataEventListener("onStatus", new WOWZDataEvent.EventListener(){
#Override
public WOWZDataMap onWZDataEvent(String eventName, WOWZDataMap eventParams) {
if(eventParams!=null)
WOWZLog.debug("onWZDataEvent -> eventName "+eventName+" = "+eventParams.toString());
return null;
}
});
// testing player data event handler.
mStreamPlayerView.registerDataEventListener("onTextData", new WOWZDataEvent.EventListener(){
#Override
public WOWZDataMap onWZDataEvent(String eventName, WOWZDataMap eventParams) {
if(eventParams!=null)
WOWZLog.debug("onWZDataEvent -> "+eventName+" = "+eventParams.get("text"));
return null;
}
});
} else {
mHelp.setVisibility(View.GONE);
mStatusView.setErrorMessage(WowzaGoCoder.getLastError().getErrorDescription());
}
}
#Override
protected void onDestroy() {
if (mVolumeSettingChangeObserver != null)
getApplicationContext().getContentResolver().unregisterContentObserver(mVolumeSettingChangeObserver);
super.onDestroy();
}
/**
* Android Activity class methods
*/
#Override
protected void onResume() {
super.onResume();
syncUIControlState();
}
#Override
protected void onPause() {
if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.stop();
// Wait for the streaming player to disconnect and shutdown...
mStreamPlayerView.getCurrentStatus().waitForState(WOWZState.IDLE);
}
super.onPause();
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
public boolean isPlayerConfigReady()
{
return false;
}
/*
Click handler for network pausing
*/
public void onPauseNetwork(View v)
{
Button btn = (Button)findViewById(R.id.pause_network);
if(btn.getText().toString().trim().equalsIgnoreCase("pause network")) {
WOWZLog.info("Pausing network...");
btn.setText("Unpause Network");
mStreamPlayerView.pauseNetworkStack();
}
else{
WOWZLog.info("Unpausing network... btn.getText(): "+btn.getText());
btn.setText("Pause Network");
mStreamPlayerView.unpauseNetworkStack();
}
}
/**
* Click handler for the playback button
*/
public void onTogglePlayStream(View v) {
if (mStreamPlayerView.isPlaying()) {
mStreamPlayerView.stop();
} else if (mStreamPlayerView.isReadyToPlay()) {
if(!this.isNetworkAvailable()){
displayErrorDialog("No internet connection, please try again later.");
return;
}
// if(!this.isPlayerConfigReady()){
// displayErrorDialog("Please be sure to include a host, stream, and application to playback a stream.");
// return;
// }
mHelp.setVisibility(View.GONE);
WOWZStreamingError configValidationError = mStreamPlayerConfig.validateForPlayback();
if (configValidationError != null) {
mStatusView.setErrorMessage(configValidationError.getErrorDescription());
} else {
// Set the detail level for network logging output
mStreamPlayerView.setLogLevel(mWZNetworkLogLevel);
// Set the player's pre-buffer duration as stored in the app prefs
float preBufferDuration = GoCoderSDKPrefs.getPreBufferDuration(PreferenceManager.getDefaultSharedPreferences(this));
mStreamPlayerConfig.setPreRollBufferDuration(preBufferDuration);
// Start playback of the live stream
mStreamPlayerView.play(mStreamPlayerConfig, this);
}
}
}
/**
* WOWZStatusCallback interface methods
*/
#Override
public synchronized void onWZStatus(WOWZStatus status) {
final WOWZStatus playerStatus = new WOWZStatus(status);
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
WOWZStatus status = new WOWZStatus(playerStatus.getState());
switch(playerStatus.getState()) {
case WOWZPlayerView.STATE_PLAYING:
// Keep the screen on while we are playing back the stream
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (mStreamPlayerConfig.getPreRollBufferDuration() == 0f) {
mTimerView.startTimer();
}
// Since we have successfully opened up the server connection, store the connection info for auto complete
GoCoderSDKPrefs.storeHostConfig(PreferenceManager.getDefaultSharedPreferences(PlayerActivity.this), mStreamPlayerConfig);
// Log the stream metadata
WOWZLog.debug(TAG, "Stream metadata:\n" + mStreamPlayerView.getMetadata());
break;
case WOWZPlayerView.STATE_READY_TO_PLAY:
// Clear the "keep screen on" flag
WOWZLog.debug(TAG, "STATE_READY_TO_PLAY player activity status!");
if(playerStatus.getLastError()!=null)
displayErrorDialog(playerStatus.getLastError());
playerStatus.clearLastError();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mTimerView.stopTimer();
break;
case WOWZPlayerView.STATE_PREBUFFERING_STARTED:
WOWZLog.debug(TAG, "Dialog for buffering should show...");
showBuffering();
break;
case WOWZPlayerView.STATE_PREBUFFERING_ENDED:
WOWZLog.debug(TAG, "Dialog for buffering should stop...");
hideBuffering();
// Make sure player wasn't signaled to shutdown
if (mStreamPlayerView.isPlaying()) {
mTimerView.startTimer();
}
break;
default:
break;
}
syncUIControlState();
}
});
}
#Override
public synchronized void onWZError(final WOWZStatus playerStatus) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
displayErrorDialog(playerStatus.getLastError());
syncUIControlState();
}
});
}
public void onToggleMute(View v) {
mBtnMic.toggleState();
if (mStreamPlayerView != null)
mStreamPlayerView.mute(!mBtnMic.isOn());
mSeekVolume.setEnabled(mBtnMic.isOn());
}
public void onToggleScaleMode(View v) {
int newScaleMode = mStreamPlayerView.getScaleMode() == WOWZMediaConfig.RESIZE_TO_ASPECT ? WOWZMediaConfig.FILL_VIEW : WOWZMediaConfig.RESIZE_TO_ASPECT;
mBtnScale.setState(newScaleMode == WOWZMediaConfig.FILL_VIEW);
mStreamPlayerView.setScaleMode(newScaleMode);
}
public void onStreamMetadata(View v) {
WOWZDataMap streamMetadata = mStreamPlayerView.getMetadata();
WOWZDataMap streamStats = mStreamPlayerView.getStreamStats();
// WOWZDataMap streamConfig = mStreamPlayerView.getStreamConfig().toDataMap();
WOWZDataMap streamConfig = new WOWZDataMap();
WOWZDataMap streamInfo = new WOWZDataMap();
streamInfo.put("- Stream Statistics -", streamStats);
streamInfo.put("- Stream Metadata -", streamMetadata);
//streamInfo.put("- Stream Configuration -", streamConfig);
DataTableFragment dataTableFragment = DataTableFragment.newInstance("Stream Information", streamInfo, false, false);
getFragmentManager().beginTransaction()
.add(android.R.id.content, dataTableFragment)
.addToBackStack("metadata_fragment")
.commit();
}
public void onSettings(View v) {
// Display the prefs fragment
GoCoderSDKPrefs.PrefsFragment prefsFragment = new GoCoderSDKPrefs.PrefsFragment();
prefsFragment.setFixedSource(true);
prefsFragment.setForPlayback(true);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, prefsFragment)
.addToBackStack(null)
.commit();
}
private void syncUIControlState() {
boolean disableControls = (!(mStreamPlayerView.isReadyToPlay() || mStreamPlayerView.isPlaying()) || sGoCoderSDK == null);
if (disableControls) {
mBtnPlayStream.setEnabled(false);
mBtnSettings.setEnabled(false);
mSeekVolume.setEnabled(false);
mBtnScale.setEnabled(false);
mBtnMic.setEnabled(false);
mStreamMetadata.setEnabled(false);
} else {
mBtnPlayStream.setState(mStreamPlayerView.isPlaying());
mBtnPlayStream.setEnabled(true);
if (mStreamPlayerConfig.isAudioEnabled()) {
mBtnMic.setVisibility(View.VISIBLE);
mBtnMic.setEnabled(true);
mSeekVolume.setVisibility(View.VISIBLE);
mSeekVolume.setEnabled(mBtnMic.isOn());
mSeekVolume.setProgress(mStreamPlayerView.getVolume());
} else {
mSeekVolume.setVisibility(View.GONE);
mBtnMic.setVisibility(View.GONE);
}
mBtnScale.setVisibility(View.VISIBLE);
mBtnScale.setVisibility(mStreamPlayerView.isPlaying() && mStreamPlayerConfig.isVideoEnabled() ? View.VISIBLE : View.GONE);
mBtnScale.setEnabled(mStreamPlayerView.isPlaying() && mStreamPlayerConfig.isVideoEnabled());
mBtnSettings.setEnabled(!mStreamPlayerView.isPlaying());
mBtnSettings.setVisibility(mStreamPlayerView.isPlaying() ? View.GONE : View.VISIBLE);
mStreamMetadata.setEnabled(mStreamPlayerView.isPlaying());
mStreamMetadata.setVisibility(mStreamPlayerView.isPlaying() ? View.VISIBLE : View.GONE);
}
}
private void showBuffering() {
try {
if (mBufferingDialog == null) return;
mBufferingDialog.show();
}
catch(Exception ex){}
}
private void cancelBuffering(DialogInterface dialogInterface) {
if(mStreamPlayerConfig.getHLSBackupURL()!=null || mStreamPlayerConfig.isHLSEnabled()){
mStreamPlayerView.stop(true);
}
else if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.stop(true);
}
}
private void hideBuffering() {
if (mBufferingDialog.isShowing())
mBufferingDialog.dismiss();
}
#Override
public void syncPreferences() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
mWZNetworkLogLevel = Integer.valueOf(prefs.getString("wz_debug_net_log_level", String.valueOf(WOWZLog.LOG_LEVEL_DEBUG)));
mStreamPlayerConfig.setIsPlayback(true);
if (mStreamPlayerConfig != null)
GoCoderSDKPrefs.updateConfigFromPrefsForPlayer(prefs, mStreamPlayerConfig);
}
private class StatusCallback implements WOWZStatusCallback {
#Override
public void onWZStatus(WOWZStatus wzStatus) {
}
#Override
public void onWZError(WOWZStatus wzStatus) {
}
}
}
The error I get is;
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.wowza.gocoder.sdk.sampleapp/com.wowza.gocoder.sdk.sampleapp.PlayerActivity}: java.lang.RuntimeException: Invalid surface: null
You start the stream in onCreate. At this time the Surface used by WOWZPlayerView is not ready yet and the app crashes with the 'Invalid surface' error.
If you look at the sample test in the GoCoder SDK, the playback is started when the user clicks a button. Eg. when the Surface is valid.
Create a button and move your 'mStreamPlayerView.play(mStreamPlayerConfig, statusCallback);' to the button.onClick.
Or ... use any GoCoder SDK v1.7 and more recent.
Please, let me know if I can help any further.
Thanks
I am making an app which consists of an activity and a service. By pressing a button the service is started, it collects data in the background from a sensor and classifies it and outputs a string. I want to display the string in a textView. Right now I can see in the log that the variable is updated 2 times every second, but when I try and update the textView from the service class nothing is happening unless I press the button, whenever I press the button, the string is displayed in the textView.
What is the easiest solution here? I tried to make the textView static and it still can't update it. Can you make it so that the view is updated automatically every second? Can I add a listener somehow? Since I am not very experienced I would like an easy solution that does not have to be a "good" one.
Here is my code
Activity:
public class CollectorActivity extends Activity {
private enum State {
IDLE, COLLECTING, TRAINING, CLASSIFYING
};
private final String[] mLabels = { Globals.CLASS_LABEL_STANDING,
Globals.CLASS_LABEL_WALKING, Globals.CLASS_LABEL_RUNNING,
Globals.CLASS_LABEL_OTHER };
private RadioGroup radioGroup;
private final RadioButton[] radioBtns = new RadioButton[4];
private Intent mServiceIntent;
private File mFeatureFile;
public static TextView mCurrentLabel;
private State mState;
private Button btnDelete;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
radioGroup = (RadioGroup) findViewById(R.id.radioGroupLabels);
radioBtns[0] = (RadioButton) findViewById(R.id.radioStanding);
radioBtns[1] = (RadioButton) findViewById(R.id.radioWalking);
radioBtns[2] = (RadioButton) findViewById(R.id.radioRunning);
radioBtns[3] = (RadioButton) findViewById(R.id.radioOther);
btnDelete = (Button) findViewById(R.id.btnDeleteData);
mCurrentLabel = (TextView) findViewById(R.id.textView);
mState = State.IDLE;
mFeatureFile = new File(getExternalFilesDir(null),
Globals.FEATURE_FILE_NAME);
mServiceIntent = new Intent(this, SensorsService.class);
}
public void onCollectClicked(View view) {
if (mState == State.IDLE) {
mState = State.COLLECTING;
((Button) view).setText(R.string.ui_collector_button_stop_title);
btnDelete.setEnabled(false);
radioBtns[0].setEnabled(false);
radioBtns[1].setEnabled(false);
radioBtns[2].setEnabled(false);
radioBtns[3].setEnabled(false);
int acvitivtyId = radioGroup.indexOfChild(findViewById(radioGroup
.getCheckedRadioButtonId()));
String label = mLabels[acvitivtyId];
Bundle extras = new Bundle();
extras.putString(Globals.CLASS_LABEL_KEY, label);
mServiceIntent.putExtras(extras);
startService(mServiceIntent);
} else if (mState == State.COLLECTING) {
mState = State.IDLE;
((Button) view).setText(R.string.ui_collector_button_start_title);
btnDelete.setEnabled(true);
radioBtns[0].setEnabled(true);
radioBtns[1].setEnabled(true);
radioBtns[2].setEnabled(true);
radioBtns[3].setEnabled(true);
stopService(mServiceIntent);
((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancelAll();
}
}
public void onDeleteDataClicked(View view) {
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
if (mFeatureFile.exists()) {
mFeatureFile.delete();
}
Toast.makeText(getApplicationContext(),
R.string.ui_collector_toast_file_deleted,
Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBackPressed() {
if (mState == State.TRAINING) {
return;
} else if (mState == State.COLLECTING || mState == State.CLASSIFYING) {
stopService(mServiceIntent);
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
.cancel(Globals.NOTIFICATION_ID);
}
super.onBackPressed();
}
#Override
public void onDestroy() {
// Stop the service and the notification.
// Need to check whether the mSensorService is null or not.
if (mState == State.TRAINING) {
return;
} else if (mState == State.COLLECTING || mState == State.CLASSIFYING) {
stopService(mServiceIntent);
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
.cancelAll();
}
finish();
super.onDestroy();
}
And this is the "doInBackground" method in my service class. The line "CollectorActivity.mCurrentLabel.setText(classification);" is the problem. I want this to update the textView continously.
public class OnSensorChangedTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
Instance inst = new DenseInstance(mFeatLen);
inst.setDataset(mDataset);
Instance inst2 = new DenseInstance(65);
int blockSize = 0;
FFT fft = new FFT(Globals.ACCELEROMETER_BLOCK_CAPACITY);
double[] accBlock = new double[Globals.ACCELEROMETER_BLOCK_CAPACITY];
double[] re = accBlock;
double[] im = new double[Globals.ACCELEROMETER_BLOCK_CAPACITY];
double max = Double.MIN_VALUE;
while (true) {
try {
// need to check if the AsyncTask is cancelled or not in the while loop
if (isCancelled () == true)
{
return null;
}
// Dumping buffer
accBlock[blockSize++] = mAccBuffer.take().doubleValue();
if (blockSize == Globals.ACCELEROMETER_BLOCK_CAPACITY) {
blockSize = 0;
testList = new ArrayList<Double>();
// time = System.currentTimeMillis();
max = .0;
for (double val : accBlock) {
if (max < val) {
max = val;
}
}
fft.fft(re, im);
for (int i = 0; i < re.length; i++) {
double mag = Math.sqrt(re[i] * re[i] + im[i]
* im[i]);
inst.setValue(i, mag);
testList.add(i,mag);
im[i] = .0; // Clear the field
}
// Append max after frequency component
inst.setValue(Globals.ACCELEROMETER_BLOCK_CAPACITY, max);
inst2.setValue(Globals.ACCELEROMETER_BLOCK_CAPACITY, max);
testList.add(max);
classificationIndex = WekaClassifier.classify(testList.toArray());
classification = testLabel.get((int) classificationIndex);
CollectorActivity.mCurrentLabel.setText(classification);
inst.setValue(mClassAttribute, mLabel);
mDataset.add(inst);
Log.i("new instance", mDataset.size() + "");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
In doInBackground(Void... arg0) change CollectorActivity.mCurrentLabel.setText(classification); to publishProgress(classification); then change second argument from Void to String: public class OnSensorChangedTask extends AsyncTask<Void, Srting, Void> and add onProgressUpdate().
Finally your code should looks like:
public class OnSensorChangedTask extends AsyncTask<Void, Srting, Void> {
#Override
protected Void doInBackground(Void... arg0) {
//...
publishProgress(classification);
//...
}
#Override
protected Void onProgressUpdate(String... classification) {
CollectorActivity.mCurrentLabel.setText(classification[0]);
}
I have a splash screen using AsyncTask, it will download some data from database and store the data in ArrayList. This ArrayList will be used for RecyclerView in fragments of MainActivity.class.
The problem is when I run the app from Android Studio to my phone, everything works perfectly. But, when I destroy the app and run it manually from my phone it will display blank white screen and then it will crash. And if I run once again after it crashed, the app will work. So, this app will always work only if I run it from Android Studio or after it crashed.
The error says that it is caused by the empty list. If I'm not mistaken, I think the AsyncTask doesn't seem to work properly after the activity is destroyed. But I don't know how to fix it. Please help me to solve this problem.
SplashScreen.java
public class SplashScreenActivity extends AppCompatActivity {
public static Event event;
private static List<Feed> feedList;
private static List<Event> eventList;
private static List<Event> todayList;
private static List<Event> upcomingList;
private static List<Partner> partnerList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splashscreen);
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
Config.TODAY_DATE = String.valueOf(today.monthDay) + "-" + String.valueOf(today.month) + "-" + String.valueOf(today.year);
new DownloadData().execute("");
}
class DownloadData extends AsyncTask<String, Integer, String>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
startActivity(new Intent(getBaseContext(), WelcomeActivity.class));
finish();
}
#Override
protected String doInBackground(String... params) {
RequestHandler rh = new RequestHandler();
String JSON_STRING = rh.sendGetRequest(Config.URL_GET_ALL_DATA);
JSONObject jsonObject;
eventList = new ArrayList<>();
todayList = new ArrayList<>();
upcomingList = new ArrayList<>();
partnerList = new ArrayList<>();
feedList = new ArrayList<>();
try {
jsonObject = new JSONObject(JSON_STRING);
JSONArray getEvent = jsonObject.getJSONArray(Config.TAG_JSON_EVENT);
for (int i = 0; i < getEvent.length(); i++) {
int id = getEvent.getJSONObject(i).getInt(Config.TAG_ID);
int eoId = getEvent.getJSONObject(i).getInt(Config.TAG_EO_ID);
String eoName = getEvent.getJSONObject(i).getString(Config.TAG_EO_NAME);
String title = getEvent.getJSONObject(i).getString(Config.TAG_TITLE);
String day = getEvent.getJSONObject(i).getString(Config.TAG_DAY);
String date = getEvent.getJSONObject(i).getString(Config.TAG_DATE);
int price = getEvent.getJSONObject(i).getInt(Config.TAG_PRICE);
event = new Event(id, eoId, eoName, title, day, date, price);
eventList.add(event);
if(Config.TODAY_DATE.equals(event.getDate())){
todayList.add(event);
} else {
upcomingList.add(event);
}
}
JSONArray getPartner = jsonObject.getJSONArray(Config.TAG_JSON_PARTNER);
for (int i = 0; i < getPartner.length(); i++) {
int pId = getPartner.getJSONObject(i).getInt(Config.TAG_ID);
String pName = getPartner.getJSONObject(i).getString(Config.TAG_NAME);
String pEmail = getPartner.getJSONObject(i).getString(Config.TAG_EMAIL);
String pPhone = getPartner.getJSONObject(i).getString(Config.TAG_PHONE);
String pPhoto = getPartner.getJSONObject(i).getString(Config.TAG_PHOTO_URL);
Partner partner = new Partner(pId, pName, pEmail, pPhone, pPhoto);
partnerList.add(partner);
}
JSONArray getArticle = jsonObject.getJSONArray(Config.TAG_JSON_ARTICLE);
for (int i = 0; i < getArticle.length(); i++) {
int feedId = getArticle.getJSONObject(i).getInt(Config.TAG_ID);
String feedAuthor = getArticle.getJSONObject(i).getString(Config.TAG_FEED_AUTHOR);
String feedTitle = getArticle.getJSONObject(i).getString(Config.TAG_FEED_TITLE);
String feedContent = getArticle.getJSONObject(i).getString(Config.TAG_FEED_CONTENT);
String feedDate = getArticle.getJSONObject(i).getString(Config.TAG_FEED_DATE);
String feedThumbnail = getArticle.getJSONObject(i).getString(Config.TAG_FEED_THUMBNAIL);
Feed feed = new Feed(feedId, feedAuthor, feedTitle, feedContent, feedDate, feedThumbnail);
feedList.add(feed);
}
} catch (JSONException e) {
e.printStackTrace();
}
return JSON_STRING;
}
}
public static List<Feed> getFeedList(){ return feedList;}
public static List<Event> getEventList() {return eventList;}
public static List<Event> getTodayList() { return todayList;}
public static List<Event> getUpcomingList() { return upcomingList;}
public static List<Partner> getPartnerList() {return partnerList;}
}
DiscoverFragment.java
public class DiscoverFragment extends Fragment implements ViewPager.OnPageChangeListener, View.OnClickListener {
protected View view;
private LinearLayout pager_indicator;
private int dotsCount;
private ImageView[] dots;
private List<Feed> feedList;
private List<Event> eventList;
private List<Partner> partnerList;
public DiscoverFragment() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_discover, container, false);
RecyclerView recyclerViewEvent = (RecyclerView) view.findViewById(R.id.discover_event_recycler_view);
RecyclerView recyclerViewPartner = (RecyclerView) view.findViewById(R.id.discover_partner_recycler_view);
ClickableViewPager intro_images = (ClickableViewPager) view.findViewById(R.id.pager_introduction);
pager_indicator = (LinearLayout) view.findViewById(R.id.viewPagerCountDots);
eventList = SplashScreenActivity.getEventList();
partnerList = SplashScreenActivity.getPartnerList();
feedList = SplashScreenActivity.getFeedList();
EventAdapter eventAdapter = new EventAdapter(getContext(), eventList);
DiscoverPartnerAdapter discoverPartnerAdapter = new DiscoverPartnerAdapter(getContext(), partnerList);
DiscoverFeedAdapter mAdapter = new DiscoverFeedAdapter(getContext(), feedList);
final LinearLayoutManager layoutManagerEvent = new LinearLayoutManager(getContext());
final LinearLayoutManager layoutManagerPartner = new LinearLayoutManager(getContext());
layoutManagerEvent.setOrientation(LinearLayoutManager.HORIZONTAL);
layoutManagerPartner.setOrientation(LinearLayoutManager.HORIZONTAL);
addBottomDots(0);
intro_images.setAdapter(mAdapter);
intro_images.setCurrentItem(0);
intro_images.addOnPageChangeListener(this);
intro_images.setOnItemClickListener(new ClickableViewPager.OnItemClickListener() {
#Override
public void onItemClick(int position) {
Config.FEED_ID = position;
startActivity(new Intent(getContext(), ArticleActivity.class));
}
});
return view;
}
private void addBottomDots(int currentPage) {
dots = new ImageView[feedList.size()]; //the problem
pager_indicator.removeAllViews();
for (int i = 0; i < dots.length; i++) {
dots[i] = new ImageView(getContext());
dots[i].setImageDrawable(getResources().getDrawable(R.drawable.nonselecteditem_dot));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(4, 0, 4, 0);
pager_indicator.addView(dots[i], params);
}
if (dots.length > 0)
dots[currentPage].setImageDrawable(getResources().getDrawable(R.drawable.selecteditem_dot));
}
#Override
public void onClick(View v) {
switch (v.getId()) {
}
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
addBottomDots(position);
for (int i = 0; i < dotsCount; i++) {
dots[i].setImageDrawable(getResources().getDrawable(R.drawable.nonselecteditem_dot));
}
dots[position].setImageDrawable(getResources().getDrawable(R.drawable.selecteditem_dot));
}
}
LogCat
01-29 00:40:57.565 32535-32535/com.irmaelita.esodiaapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.irmaelita.esodiaapp, PID: 32535
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at com.irmaelita.esodiaapp.fragment.DiscoverFragment.addBottomDots(DiscoverFragment.java:181)
at com.irmaelita.esodiaapp.fragment.DiscoverFragment.onCreateView(DiscoverFragment.java:158)
feedList is null. You create feedList instance when DownloadData task is executed. But you call feedList.size() in addBottomDots when fragment view should be created. So, most probably addBottomDots is called before DownloadData task is executed. You need to fix it.
The feedlist in your discover fragment is going empty while initializing. Please set a null check before doing so.It not about running from android studio.If I have understood it correctly you are trying to access a list from splasScreen activity after finishing it. ie in post execute you finish the current activity and the fragment is in main activity,so the list is going null.So if this is the case (and please correct me if not) then either download the data somewhere centrally or best way send it to main activity with intent and use it there. Also when running from android studio kill the app manually and run it again,while the phone is connected and see if it crashes in current scenario.
Send your data from doInBackground to MainActivity with sendBroadcast
Add broadcast method in DownloadData class
private void broadcast(SplashParcel parcel) {
Intent i = new Intent("splash_parcel");
i.putExtra("values", parcel);
sendBroadcast(i);
}
#Override
protected String doInBackground(String... params) {
// your code
// ..
try {
// your code
// ..
// send splashParcel to MainActivity
SplashParcel splashParcel = new SplashParcel(feedList, eventList, todayList, upcomingList, partnerList);
broadcast (splashParcel);
} catch (JSONException e) {
e.printStackTrace();
}
return JSON_STRING;
}
Add new class SplashParcel.java
public class SplashParcel implements Parcelable {
public static final Creator<SplashParcel> CREATOR = new Creator<SplashParcel>() {
#Override
public SplashParcel createFromParcel(Parcel in) {
return new SplashParcel(in);
}
#Override
public SplashParcel[] newArray(int size) {
return new SplashParcel[size];
}
};
private static List<Feed> _feedList;
private static List<Event> _eventList;
private static List<Event> _todayList;
private static List<Event> _upcomingList;
private static List<Partner> _partnerList;
protected SplashParcel(Parcel in) {
_feedList = new ArrayList<Feed>();
in.readList(_feedList, null);
_eventList = new ArrayList<Event>();
in.readList(_eventList, null);
_todayList = new ArrayList<Event>();
in.readList(_todayList, null);
_upcomingList = new ArrayList<Event>();
in.readList(_upcomingList, null);
_partnerList = new ArrayList<Partner>();
in.readList(_partnerList, null);
}
public SplashParcel(List<Feed> feedList, List<Event> eventList, List<Event> todayList, List<Event> upcomingList, List<Partner> partnerList) {
_feedList = feedList;
_eventList = eventList;
_todayList = todayList;
_upcomingList = upcomingList;
_partnerList = partnerList;
}
public SplashParcel() {
}
public List<Feed> getFeedList() {
return _feedList;
}
public void setFeedList(List<Feed> feedList) {
_feedList = feedList;
}
public List<Event> getEventList() {
return _eventList;
}
public void setEventList(List<Event> eventList) {
_eventList = eventList;
}
public List<Event> getTodayList() {
return _todayList;
}
public void setTodayList(List<Event> todayList) {
_todayList = todayList;
}
public List<Event> getUpcomingList() {
return _upcomingList;
}
public void setUpcomingList(List<Event> upcomingList) {
_upcomingList = upcomingList;
}
public List<Partner> getPartnerList() {
return _partnerList;
}
public void setPartnerList(List<Partner> partnerList) {
_partnerList = partnerList;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeList(_feedList);
parcel.writeList(_eventList);
parcel.writeList(_todayList);
parcel.writeList(_upcomingList);
parcel.writeList(_partnerList);
}
}
MainActivity.java
// member variable
private BroadcastReceiver _splashReceiver;
private Bundle _bundle = new Bundle();
#Override
protected void onResume() {
super.onResume();
splashReceiver();
}
// receive splashParcel from SplashScreenActivity
private void splashReceiver() {
if (_splashReceiver == null) {
_splashReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
SplashParcel splashParcel = intent.getParcelableExtra("values");
if (splashParcel != null) {
// save splashParcel into _budle
_bundle.putParcelable("splash_parcel", splashParcel);
}
}
};
registerReceiver(_splashReceiver, new IntentFilter("splash_parcel"));
}
}
//Send _bundle to DiscoverFragment
private void showDiscoverFragment(){
if(_bundle != null) {
// create instance of discoverFragment with passing _bundle as arguments
DiscoverFragment discoverFragment = new DiscoverFragment();
discoverFragment.setArguments(_bundle);
// replace activity_main.xml with discoverFragment
getSupportFragmentManager().beginTransaction().replace(R.id.main_container, discoverFragment).addBackStack(null).commit();
}
}
In onCreateView of DiscoverFragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
SplashParcel splashParcel = getArguments().getParcelable("splash_parcel");
if(splashParcel != null) {
// your splashParcel ready in here
List<Feed> feedList = splashParcel.getFeedList()
List<Event> eventList = splashParcel.getEventList()
List<Event> todayList = splashParcel.getTodayList();
List<Event> upcommingList = splashParcel.getUpcomingList();
List<Partner> partnerList = splashParcel.getPartnerList();
}
}
Im new to Android Developement and currently working on an app that should give me the time between first time clicking a button and second time clicking the button and add it to a currently selected customer.
Current Status of App:
I established a connection to da mySql Database using Volley and a local webservice.
It works to insert my customers and time stamps to the table, but when loading times for a specific customer i get a strange result in one case. I tried debugging it but the app keeps crashing on debugging without a message. When not debugging it doesnt crash but shows weird data.
To the problem:
In my main activity called "ZeitErfassen" i have a button to get an overview of all customers display in a ListView.
I create the Listview with a custom ArrayAdapter because i want to pass my objects to the next Activity where my customers are displayed.
So onCreate of the overview of customers i create a new arraylist and fill it with all customers from my database. this list i pass to my customadapter and then set it as my adapter of the Listview.
Now, when i click on an item, i call a php script and pass the customer_id to the query to fetch all times from database where customer_id = customer_id.
Now the part where i get "strange" data...
1.(Source:ZeitErfassen;Destination:AddCustomer) I create a new customer,example xyz, in the app, data gets passed to the database.
2.(Source:ZeitErfassen;Destination:DisplayCustomer) I call my overview for all customers where the ListView is filled with data as described above. At the end ob the List I see the customer i just created,xyz.
3.Go back to Main Activity(ZeitErfassen)
4.(Source:ZeitErfassen;Destination:DisplayCustomer)I open the overview for all customers again, and it shows my last created user two times! so last entry, xyz, entry before last, xyz!
After that, i can open the view as many times as i want, the customer never gets duplicated again!
The debugger stopps after step 2.
Now when i click on the new customers, it calls the script to fetch the times by customer_id.
One of the xyz entrys display the correct times from database.
The second one, i just found out, display the times where customer_id="". In the database the value for "" is 0.
I have no clue where the second customer suddenly appears from and debugging didnt help me either -.-
When i close the app an open it again, there ist just one entry for the user that was visible twice before closing the app. It doesnt duplicate on opening view...
Here is my code..
Main Activity ZeitErfassen
public class ZeitErfassen extends AppCompatActivity {
public static LinkedList<Kunde> kunden = new LinkedList<Kunde>();
boolean running = false;
long startTime,endTime,totalTime;
private SharedPreferences app_preferences;
private SharedPreferences.Editor editor;
private TextView displayTime;
public Button startEndButton;
private ArrayAdapter<String> adapter;
private Spinner spinner;
public static Kunde selectedCustomer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zeit_erfassen);
//Einstellungen laden
app_preferences = getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE);
startTime= app_preferences.getLong("startTime", 0);
endTime = app_preferences.getLong("endTime", 0);
running = app_preferences.getBoolean("running", false);
displayTime = (TextView)findViewById(R.id.zeit_bei_Kunde);
displayTime.setText((CharSequence) app_preferences.getString("zeitAnzeige", "Zeit bei Kunde"));
startEndButton = (Button)findViewById(R.id.start_Timer);
startEndButton.setText((CharSequence) app_preferences.getString("timerButton", "Start Timer"));
DatabaseHelper.customerFromDatabaseToList(this);
editor = app_preferences.edit();
editor.commit();
}
public void onDestroy() {
super.onDestroy();
editor.putLong("startTime", startTime);
editor.putString("zeitAnzeige", (String) displayTime.getText());
editor.putString("timerButton", (String) startEndButton.getText());
editor.putLong("endTime", endTime);
editor.putLong("totalTime", totalTime);
editor.putBoolean("running", app_preferences.getBoolean("running", false));
editor.commit();
this.finish();
}
public void onResume() {
super.onResume();
// saveCustomers();
// createDropDown();
}
public void startTimer(View view) {
editor = app_preferences.edit();
if(running == false) {
startTime = getTime();
running = true;
editor.putLong("startTime", startTime);
startEndButton.setText("End Timer");
displayTime.setText("Zeitstoppung läuft");
editor.putString("zeitAnzeige", (String) displayTime.getText());
editor.putString("timerButton", (String) startEndButton.getText());
editor.putBoolean("running", true);
editor.commit();
} else {
setSelectedCustomer();
endTime = getTime();
editor.putLong("endTime",endTime);
totalTime = endTime - startTime;
editor.putLong("totalTime", totalTime);
displayTime.setText(formatTime(totalTime));
editor.putString("zeitAnzeige", (String) displayTime.getText());
startEndButton.setText("Start Timer");
editor.putString("timerButton", (String) startEndButton.getText());
running = false;
editor.putBoolean("running", false);
editor.commit();
DatabaseHelper.timeToDatabase(String.valueOf(selectedCustomer.getId()),formatTime(totalTime),this);
// selectedCustomer.saveTimeToCustomer(selectedCustomer, formatTimeForCustomer(totalTime));
}
}
public String formatTime(Long totalTime) {
int hours = (int) ((totalTime / (1000*60*60)) % 24);
int minutes = (int) ((totalTime / (1000*60)) % 60);
int seconds = (int) (totalTime / 1000) % 60;
String time = (String.valueOf(hours) + ":" + String.valueOf(minutes) + ":" + String.valueOf(seconds));
return time;
}
public String formatTimeForCustomer(Long totalTime) {
StringBuilder time = new StringBuilder();
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
time.append((String.valueOf(year) + "." + String.valueOf(month) + "." + String.valueOf(day))).append(formatTime(totalTime));
return time.toString();
}
public void neuerKunde(View view) {
Intent intent = new Intent(this, AddKunde.class);
startActivity(intent);
}
public void kundenĂbersicht(View view) {
// setSelectedCustomer();
Intent intent = new Intent(this, DisplayCustomer.class);
startActivity(intent);
}
public long getTime() {
long millis = System.currentTimeMillis();
return millis;
}
public void setSelectedCustomer() {
if(kunden.size() > 0) {
if (spinner.getSelectedItem().toString() != null) {
String tempCustomer = spinner.getSelectedItem().toString();
for (Kunde k : kunden) {
if (k.getName().equals(tempCustomer)) {
selectedCustomer = k;
}
}
}
}
}
public void createDropDown() {
/*File file = new File(this.getFilesDir(),"kunden.ser"); NOT USED BECAUSE DATABASE WORKS
if(file.exists()) {
Kunde.importFromFile(this);
}*/
if (kunden.size() > 0) {
spinner = (Spinner) findViewById(R.id.chooseCustomer);
// Create an ArrayAdapter using the string array and a default spinner layout
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, DisplayCustomer.namesOfCustomers());
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
}
}
}
DisplayCustomer(Where all customers are displayed with data from Database)
public class DisplayCustomer extends AppCompatActivity {
CustomerAdapter customerAdapter;
public ArrayAdapter<String> adapterCustomerView;
private ListView listCustomerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_customer);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ArrayList<Kunde> customerList = getCustomerObjects();
customerAdapter = new CustomerAdapter(this,customerList);
listCustomerView = (ListView)findViewById(R.id.list_View_Customers);
// adapterCustomerView = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, namesOfCustomers());
listCustomerView.setAdapter(customerAdapter);
openCustomerDetails();
}
public static ArrayList<String> namesOfCustomers() {
ArrayList<String> customerNames = new ArrayList<>();
if(ZeitErfassen.kunden.size() > 0 ) {
for (Kunde k : ZeitErfassen.kunden) {
customerNames.add(k.getName());
}
}
return customerNames;
}
public static ArrayList<Kunde> getCustomerObjects() {
ArrayList<Kunde> customerList = new ArrayList<>();
if(ZeitErfassen.kunden.size() > 0 ) {
for (Kunde k : ZeitErfassen.kunden) {
customerList.add(k);
}
}
return customerList;
}
public void openCustomerDetails() {
listCustomerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Kunde kunde = new Kunde();
kunde = (Kunde)listCustomerView.getItemAtPosition(position);
Intent intent = new Intent(DisplayCustomer.this, DisplayDetailedCustomer.class);
intent.putExtra("selectedCustomerObject",(Parcelable)kunde);
startActivity(intent);
}
});
}
}
My CustomerAdapter to pass data from one intent to another.
public class CustomerAdapter extends ArrayAdapter<Kunde> {
public CustomerAdapter(Context context, ArrayList<Kunde> customerList) {
super(context,0,customerList);
}
public View getView(int position, View convertView, ViewGroup parent) {
//Data for this position
Kunde kunde = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.items_customer_layout, parent, false);
}
// Lookup view for data population
TextView tvName = (TextView) convertView.findViewById(R.id.tvCustomerName);
// Populate the data into the template view using the data object
tvName.setText(kunde.getName());
// Return the completed view to render on screen
return convertView;
}
}
DatabaseHelper Class
public class DatabaseHelper {
public static RequestQueue requestQueue;
public static String host = "http://192.168.150.238/";
public static final String insertUrl = host+"insertCustomer.php";
public static final String showUrl = host+"showCustomer.php";
public static final String insertTimeUrl = host+"insertTime.php";
public static final String showTimeUrl = host+"showTimes.php";
public static void customerFromDatabaseToList(final Context context) {
//Display customer from database
requestQueue = Volley.newRequestQueue(context);
final ArrayList<String> customerNames = new ArrayList<>();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, showUrl, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray customers = response.getJSONArray("customers");
if(customers.length() > 0) {
for (int i = 0; i < customers.length(); i++) {
JSONObject customer = customers.getJSONObject(i);
String customerName = customer.getString("cus_name");
String customerAddress = customer.getString("cus_address");
int customerID = Integer.valueOf(customer.getString("cus_id"));
if (customerName != null && customerAddress != null) {
try {
Kunde k = new Kunde(customerName, customerAddress, customerID);
if (!listContainsObject(k)) {
ZeitErfassen.kunden.add(k);
}
} catch (Exception e) {
showAlert("Fehler in customerFromDatabaseToListn!", "Fehler", context);
}
} else {
showAlert("Fehler in customerFromDatabaseToListn!", "Fehler", context);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
requestQueue.add(jsonObjectRequest);
}
public static boolean listContainsObject(Kunde cust) {
for(Kunde k : ZeitErfassen.kunden) {
if(k.getId() == cust.getId()) {
return true;
}
}
return false;
}
public static void timeToDatabase(final String customer_id, final String time_value, final Context context) {
requestQueue = Volley.newRequestQueue(context);
StringRequest request = new StringRequest(Request.Method.POST, DatabaseHelper.insertTimeUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
showAlert("Fehler","Fehler bei Verbindung zur Datenbank",context);
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> parameters = new HashMap<String,String>();
parameters.put("customerid",customer_id);
parameters.put("timevalue",time_value);
return parameters;
}
};
requestQueue.add(request);
};
public static void showAlert(String title, String message, Context context) {
// 1. Instantiate an AlertDialog.Builder with its constructor
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// 2. Chain together various setter methods to set the dialog characteristics
builder.setMessage(message)
.setTitle(title);
// 3. Get the AlertDialog from create()
AlertDialog dialog = builder.create();
}
public static ArrayList<String> timesFromDataBaseToList(final Context context,final int customer_id) {
requestQueue = Volley.newRequestQueue(context);
final String cus_id = String.valueOf(customer_id) ;
final ArrayList<String> customerTimes = new ArrayList<>();
StringRequest jsonObjectRequest = new StringRequest(Request.Method.POST, showTimeUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject object = new JSONObject(response.toString());
JSONArray times = object.getJSONArray("customertimes");
if (times.length() > 0) {
for (int i = 0; i < times.length(); i++) {
JSONObject jsonObject = times.getJSONObject(i);
String timeValue = jsonObject.getString("time_value");
if (timeValue != null) {
customerTimes.add(timeValue);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context,"Fehler beim Holen der Zeiten",Toast.LENGTH_LONG).show();
error.printStackTrace();
}
}){
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> parameters = new HashMap<String,String>();
parameters.put("cus_id",cus_id);
return parameters;
}
};
requestQueue.add(jsonObjectRequest);
return customerTimes;
};
}
DisplayDetailedCustomer / Display the times
public class DisplayDetailedCustomer extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_detailed_customer);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent getCustomerParcable = getIntent();
Kunde customer = getCustomerParcable.getExtras().getParcelable("selectedCustomerObject");
TextView displayCustomerNameDetailed =(TextView) findViewById(R.id.detailedCustomerViewName);
TextView displayCustomerAddressDetailed =(TextView) findViewById(R.id.detailedCustomerAddress);
ListView timeListView = (ListView)findViewById(R.id.detailedTimeListView);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, DatabaseHelper.timesFromDataBaseToList(this,customer.getId()));
timeListView.setAdapter(adapter);
displayCustomerNameDetailed.setText(customer.getName());
displayCustomerAddressDetailed.setText(customer.getAdresse());
}
}
Kunde Class / Customer Class with interface Parcelable
public class Kunde implements Serializable,Parcelable {
private String name;
private String adresse;
private int id;
public LinkedList<String> zeiten;
public Kunde(String name, String adresse) throws Exception{
setName(name);
setAdresse(adresse);
zeiten = new LinkedList<String>();
}
public Kunde(String name, String adresse,int id) throws Exception{
setName(name);
setAdresse(adresse);
setId(id);
zeiten = new LinkedList<String>();
}
public Kunde(){};
public void setId(int id) {
this.id = id;
}
public int getId(){
return id;
}
public void setName(String name) throws Exception {
if(name != null) {
this.name = name;
} else throw new Exception("Name ist ungueltig! in setName");
}
public void setAdresse(String adresse) throws Exception{
if(adresse != null) {
this.adresse = adresse;
}else throw new Exception("Adresse ist ungueltig! in setAdresse");
}
public String getName() {
return name;
}
public String getAdresse() {
return adresse;
}
public void saveZeit(Long totalTime) {
zeiten.add(String.valueOf(totalTime));
}
public void saveTimeToCustomer(Kunde customer,String time){
customer.zeiten.add(time);
}
//------------------------------------Parcelable Methods to pass Daata from one Intent to another----------------------------------------
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.name);
dest.writeString(this.adresse);
// dest.writeList(this.zeiten);
}
// this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
public static final Parcelable.Creator<Kunde> CREATOR = new Parcelable.Creator<Kunde>() {
public Kunde createFromParcel(Parcel in) {
return new Kunde(in);
}
public Kunde[] newArray(int size) {
return new Kunde[size];
}
};
// example constructor that takes a Parcel and gives you an object populated with it's values
private Kunde(Parcel in) {
LinkedList<String> zeiten = null;
id = in.readInt();
name = in.readString();
adresse = in.readString();
}
}
Thanks for taking your time!!
I haver a list view in my android app that needs to be updated. Everything works fine, but the content is reloading every second time. For example if I reload the content once, the notifyDataSetChanged() is called, but nothing changes. On my second refresh, the data is reloaded. My third time same as first and so on.. What could be the problem? Here's my code:
private class LoadMoreDataTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
ParseQuery<ParseObject> likeQuery = ParseQuery.getQuery("Likes");
likeQuery.whereEqualTo("username", ParseUser.getCurrentUser().getUsername());
likeQuery.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> likeList, ParseException e) {
if (e == null) {
postList.clear();
try {
query = new ParseQuery<ParseObject>("Images");
query.orderByDescending("createdAt");
query.setLimit(limit += 20);
ob = query.find();
for (ParseObject num : ob) {
PostRow test1;
Like singleLike = new Like(true);
for (int i = 0; i < likeList.size(); i++) {
if (likeList.get(i).get("imgId").equals(num.getObjectId())) {
isLiked = true;
break;
} else {
isLiked = false;
}
}
singleLike.setLikeStatus(isLiked);
ParseFile img = (ParseFile) num.get("img");
test1 = new PostRow(img.getUrl().toString(), (String) num.get("username"), num.getObjectId(), singleLike, num.getInt("likeCount"));
postList.add(test1);
}
} catch (ParseException e1) {
e1.printStackTrace();
}
} else {
//error
}
}
});
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
adapter.notifyDataSetChanged();
int position = listViewPosts.getFirstVisiblePosition();
View v = listViewPosts.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
listViewPosts.setSelectionFromTop(position, top);
}
}
Here's where I call the Async Task. It's an onrefresh listener, in another AsyncTask's onPostExecute method:
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new LoadMoreDataTask().execute();
swipeRefreshLayout.setRefreshing(false);
}
});