Externalization/Serialization Not Working? - java

I am trying to pass a checklist object over an intent to the next activity. Here's the code:
CheckList Object (CheckList.java)
package com.test.serialization;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import android.content.Context;
import android.widget.TableLayout;
public class CheckList extends TableLayout implements Externalizable {
public String name;
public int number_of_rows;
public CheckList() {
super(SerializationActivity.context);
}
public CheckList(Context context) {
super(context);
}
#Override
public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
// TODO Auto-generated method stub
}
#Override
public void writeExternal(ObjectOutput output) throws IOException {
// TODO Auto-generated method stub
}
}
Serialization Activity (SerializationActivity.java)
package com.test.serialization;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class SerializationActivity extends Activity {
/** Called when the activity is first created. */
private SerializationActivity activity;
private CheckList checklist;
public static Context context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = this.getApplicationContext();
checklist = new CheckList(this.getApplicationContext());
checklist.name="asdasd";
checklist.number_of_rows= 5;
activity = this;
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(on_click_listener);
}
private OnClickListener on_click_listener = new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(activity, DeserializationActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("checklist", checklist);
intent.putExtra("checklist_bundle", bundle);
startActivity(intent);
}
};
}
package com.test.serialization;
import android.os.Bundle;
import android.util.Log;
public class DeserializationActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
try {
Bundle bundle = this.getIntent().getExtras();
Bundle checklist_bundle = bundle.getBundle("checklist_bundle");
CheckList checklist = (CheckList) checklist_bundle.getSerializable("checklist");
Log.d("LOG_TAG", checklist.name);
Log.d("LOG_TAG", checklist.number_of_rows);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I know it's weird to call the the context from the Activity through the static way, but I can't figure how can i do so without it when trying to serialize a view object.
The problem here is that my checklist name and number of rows will be empty and 0.
how can i pass in the values correctly?

In order to serialize an object you need to serialize the whole object graph, i.e. the top object and all objects it refers to and so on. If you try to serialize system provided objects you might encounter some native (OS provided) objects which can't be serialized. That's why serializing system objects is mostly impossible.
For the purpose of sending Views around the Android OS (e.g. Via Intent), there is a special class that you should use: RemoteViews
RemoteViews is not a view, but rather a series of commands how to build a View. You can create it from XML layout resource, manipulate it. Since it implements Parcelable you can easily add it to Intent via intent.putExtra(name, remoteViews).

you are not doing anything in writeExternal method...
its better (in your case) to use serializable interface instead of externalizable ..
Externalizable is an interface which gives the programmer the option to externalize the object in consideration (since you didn't write anything to the stream its not passing an object across).
instead of Externalizable if you use Serializable things would get serialized automatically & things would start to work.

Related

At what part of the lifecycle should you initialize objects in a fragment used by a service?

I'm working on an Android app so I can learn mobile dev and I'm stuck with this problem.
Basically in my SampleFragment class I have an adapter called mAdapter and when my TestService gets my data objects and updates my dataObjects arrayList and notifies the adapter that the data has changed the adapter isn't initialized and is null at the time. Is it a thread issue or is it associated with the fragment lifecycle?
SampleFragment.java
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class SampleFragment extends Fragment {
private static final int SEND_DELAY = 1500;
private String userName, sEventId;
private EditText etMessage;
private ImageButton btSend;
private Context applicationContext;
private View view;
private Handler handler = new Handler();
private ArrayList<Message> dataObjects = new ArrayList<>();
private MessageListAdapter mAdapter;
private Runnable initMessageAdapter = new Runnable() {
#Override
public void run() {
initMessageAdapter();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String eventName = CurrentActiveEvent.getInstance().getEventName();
Activity activity = getActivity();
activity.setTitle(eventName);
mAdapter = new MessageListAdapter(context, userName, dataObjects);
CurrentActiveUser currentUser = CurrentActiveUser.getInstance();
userName = currentUser.getUsername();
Intent intent = new Intent(activity, TestService.class);
activity.startService(intent);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_messaging, container, false);
applicationContext = getActivity();
sEventId = CurrentActiveEvent.getInstance().getEventID();
btSend = (ImageButton) view.findViewById(R.id.btSend);
handler.post(initMessageAdapter);
btSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
handler.post(new Runnable() {
#Override
public void run() {
saveMessage(body);
}
});
}
});
return view;
}
// Setup message field and posting
private void initMessageAdapter() {
etMessage = (EditText) view.findViewById(R.id.etMessage);
ListView lvChat = (ListView) view.findViewById(R.id.lvChat);
lvChat.setAdapter(mAdapter);
}
public void updatedataObjects(List<objs> newdataObjects){
this.dataObjects.clear();
this.dataObjects.addAll(newdataObjects);
mAdapter.notifyDataSetChanged();
}
}
TestService.java
import android.app.IntentService;
import android.content.Intent;
import java.util.Collections;
import java.util.List;
public class TestService extends IntentService {
private static final int MAX_RESULTS = 50;
private static final String CLASS_NAME = TestService.class.getSimpleName();
private final String sEventId = CurrentActiveEvent.getInstance().getEventID();
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public TestService() {
super(CLASS_NAME);
}
#Override
#SuppressWarnings("unchecked")
protected void onHandleIntent(Intent intent) {
if (NetworkState.isConnected(getApplicationContext())) {
Query query = new Query(Data.class);
query.whereEqualTo(Events.ID, sEventId);
query.orderByDESC(Data.CREATED_AT);
query.setLimit(MAX_RESULTS);
List objs = queryDB(query, Data.class.getSimpleName());
if (objs != null) {
Collections.reverse(objs);
new SampleFragment().updateMessages(objs);
}
}
}
}
Your problem comes from this line:
new SampleFragment().updateMessages(objs);
You are creating a new instance of your fragment inside your service. Since you are not attaching the fragment anywhere, it's lifecycle is not started and the onCreate() method is never called, which results in the NullPointerException.
IntentServices are great for executing tasks on a background thread, but they are components, that are meant to be separated from the UI - related components, like Activities and Fragments. You should never have direct communication between an IntentService and a Fragment or Activity. If you need to return a result from your IntentService, you should consider using the LocalBroadcastManager. It will fire an intent, containing the result, and you can register receivers to intercept it.
There are also other options, like Bound Services - they are created to provide an interface for their clients, and you can use this to return your result. But bear in mind, that, unlike IntentService they don't work in a background thread by default.
Since you are trying to work with a database, I recommend you take a look and the ContentProvider and ContentResolver classes. They are the recommended way of working with DBs in Android and come with loads of neat stuff.

How can make a relation between 2 class in one program?(android)

I must write a program with android which can find other ssid's and show them. I desinged it with 2 xml pages. I create an imagebutton in page2 and want to make a relation between imagebutton and searching method. It means i want to click on imagebutton and seaching method begin it's work and search ssid's and show them...
My problem is, I download my search method and because of that i can not recognize which method i must call on my setonclick method that i write for an imagebutton in second page? I try to create another class seperately for search method and call it from the second class of page2.
but i dont know how can i make a relation between these 2 calss(i mean the second and third class). Or i must write the method of searching and on click of my imagebutton in one class?
Thanks for your suggestion.this is the code that i was copy:
import java.util.Date;
import java.util.List;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class wifiScan extends Activity {
private class WifiReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context c, Intent intent) {
List<ScanResult> results = wifi.getScanResults();
Date tempDate=new Date();
String info=testNumber+" "+(tempDate.getTime()-testDate.
getTime()) +" "+results.size();
Log.i("wifiScan", info);
wifiText.setText(info);
testNumber++;
testDate=new Date();
wifi.startScan();
}
}
private TextView wifiText;
private WifiManager wifi;
private WifiReceiver receiver;
private Date testDate;
private static int testNumber=0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
testNumber=0;
wifiText = (TextView) findViewById(R.id.wifiText);
receiver=new WifiReceiver();
registerReceiver(receiver, new IntentFilte
(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
wifi =(WifiManager)getSystemService(Context.WIFI_SERVICE);
if(!wifi.isWifiEnabled()){
wifi.setWifiEnabled(true);
}
startScan();
}
#Override
public void onStop(){
super.onStop();
finish();
}
public void startScan(){
testDate=new Date();
wifi.startScan();
}
}
you_image_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(this, wifiScan.class);
getApplicationContext().startActivity(i);
}
});

I want to make password protected android application

I want to make password protected android app, but when in this simple program system is not matching two strings.
package com.pokmgr;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.text.Editable;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainPM extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pm_layout);
final EditText pin = (EditText) findViewById(R.id.pinET);
final String pass = pin.getText().toString();
final String code = "ajaj";
Button enter = (Button) findViewById(R.id.enterBtn);
enter.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if (pass.equals(code)) {
Intent in = new Intent(MainPM.this, Menu.class);
startActivity(in);
}
else {
Intent in = new Intent(MainPM.this, Menu2.class);
startActivity(in);
}
}
});
}
/*#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.pm_layout, menu);
return true;
}*/
}
I have made Menu and Menu2 class, but every time Menu2 class is accessed. Even if I enter same pass that is "ajaj" [in this code to test]
i have defined both activities in manifest file.
Can't understand why pass.eqals(code) is not working
The problem is that you are setting pass to the contents of the EditText when the activity gets created. Instead you have to retrieve the contents of your EditText inside the OnClickListener.
Like this:
public void onClick(View v) {
final String pass = pin.getText().toString();
if (pass.equals(code)) {
// do something
} else {
// do something different
}
}
Put pin.getText().toString(); inside onClick of button. You are setting variable pass before the user actually entered something in pinEt EditText.

Getting the position of a list item in Android

So I have this class here:
package phil.droid.game;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;
public class GameList extends GamesTrialActivity
{
private ListView lv1;
protected String Game_names[]={"God of War","FOS RO DAH", "dhwaud"};
private String Game_pics[]={"God of War","God of War II"};
private int pos;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.gamelist);
lv1=(ListView)findViewById(R.id.thegamelist);
lv1.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1 , Game_names));
lv1.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
pos = position;
Intent i = new Intent(GameList.this, game_viewer.class);
startActivity(i);
}
});
}
}
And then this VclassV extends the one ^above^
package phil.droid.game;
import android.os.Bundle;
import android.widget.TextView;
public class game_viewer extends GameList
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.game_template);
TextView game_title = (TextView)findViewById(R.id.GameTitle);
game_title.setText("" + pos);
}
}
The problem is at the moment that the last bit recognizes "pos" as "0" no matter what option I click on. Can someone suggest a way to make it so pos is recognized as the number element that's clicked on in the previous class?
Make pos protected, not private.
What you're trying to do can't work: The newly launched activity will not share the same storage as the parent, even if they inherit. The only way it would be possible is if the value was static, but that's not a good idea either.
What you should do instead is to send the data as part of the intent before starting the activity, e.g.:
intent.putExtra("pos", position);
and then you can pull it out in the new activity with
getIntent().getIntExtra("pos", -1); // -1 is used as default value
Also, game_viewer should most likely be a separate activity, rather than inherit from GameList.

Android/Java: Starting activity from class method

I'm trying to start a new activity from a non-activity class.
From the main menu:
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class Menu extends Activity {
Button start, options;
GameLoop Game = new GameLoop();
#Override
public void onCreate(Bundle mainStart) {
super.onCreate(mainStart);
setContentView(R.layout.menu);
start = (Button) findViewById(R.id.bStart);
options = (Button) findViewById(R.id.bOptions);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent openStart = new Intent(Menu.this, Game.class);
startActivity(openStart);
}
});
options.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context mContext = null; //Error called for mContext to be initialized so just tried setting to null. This is most likely the error cause it would make more sense for it to be equal to "getContext()" or something like that
Game.Start(mContext);//Here
}
});
}
}
I'm trying to open an activity from the Game.Start() method.
import android.content.Context;
import android.content.Intent;
public class GameLoop extends Menu{
boolean hello = false;
public void Start(Context sContext){
Intent openOptions = new Intent(sContext, Options.class);
startActivity(openOptions);
}
}
I'm not sure if using context would be the right way of going about this but I figured it was worth a try. Im entirely new to java and android so I'm pretty much lost on where to go next. Any help in what direction to take would be throughly appreciated.
Activity extends Context, so you can just use this when inside Activity.
Game.Start(Menu.this);
I use Menu.this because you are inside inner anonymous class (View.OnClickListener) where this refers to this inner class.
Do you added the new activities to the androidmanifest.xml?

Categories