I want my custom view to have an attribute that can be set via XML that defines a callback for some custom behaviour that this view would support.
I know that i can tweak a simple string to be such using reflections, but it exists in the android API as Button has android:onClick so i wonder if this is something i can get out of the box instead of reinventing the wheel.
Anyone familiar with how it is done or do i must go ahead and implement it on my own using refelections?
seeing the android source code, looks as they did the same as i was going to :
case R.styleable.View_onClick:
if (context.isRestricted()) {
throw new IllegalStateException("The android:onClick attribute cannot "
+ "be used within a restricted context");
}
final String handlerName = a.getString(attr);
if (handlerName != null) {
setOnClickListener(new OnClickListener() {
private Method mHandler;
public void More ...onClick(View v) {
if (mHandler == null) {
try {
mHandler = getContext().getClass().getMethod(handlerName,
View.class);
} catch (NoSuchMethodException e) {
int id = getId();
String idText = id == NO_ID ? "" : " with id '"
+ getContext().getResources().getResourceEntryName(
id) + "'";
throw new IllegalStateException("Could not find a method " +
handlerName + "(View) in the activity "
+ getContext().getClass() + " for onClick handler"
+ " on view " + View.this.getClass() + idText, e);
}
}
try {
mHandler.invoke(getContext(), View.this);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not execute non "
+ "public method of the activity", e);
} catch (InvocationTargetException e) {
throw new IllegalStateException("Could not execute "
+ "method of the activity", e);
}
}
});
}
So this i guess is the only way...
Related
I am trying to stop my service but it gives null object reference. this is my code ......
PendingUpdatesService.java
NetworkStateReceiver networkStateReceiver;
MarkAttendance attendance ;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
networkStateReceiver = new NetworkStateReceiver(this);
networkStateReceiver.addListener(this);
this.registerReceiver(networkStateReceiver, new IntentFilter(android.net.ConnectivityManager.CONNECTIVITY_ACTION));
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
#Override
public void onNetworkAvailable() {
Toast.makeText(this, "NW available", Toast.LENGTH_LONG).show();
SharedPreferenceSingleton.getInstance().init(getApplication());
if (SharedPreferenceSingleton.getInstance().getIntPreference(StudentsAttendanceContracts.IF_ATTENDANCE_FAILED) == 1) {
attendance = new MarkAttendance();
attendance.updateAttendance(getApplicationContext());
}
}
#Override
public void onNetworkUnavailable() {
Toast.makeText(this, "NW not available", Toast.LENGTH_LONG).show();
}
this is a class where i am trying to stop service......
MarkAttendance.java
String mClassId, mStaffId ;
String date, classAttendanceDate;
Context mContext;
SQLiteDatabase mDB;
public void updateAttendance(Context context) {
this.mContext = context;
mDB = context.openOrCreateDatabase(DatabaseContracts.BLUEWINGS_STAFF_DB_NAME, Context.MODE_PRIVATE, null);
SharedPreferenceSingleton.getInstance().init(context);
mStaffId = String.valueOf(SharedPreferenceSingleton.getInstance().getIntPreference(SharedContracts.TEACHER_STAFF_ID));
String[] parameter = {"Attendance"} ;
String query = " SELECT * FROM " + DatabaseContracts.Tables.CheckingDataOnServer.TABLE + " WHERE " + DatabaseContracts.Tables.CheckingDataOnServer.MODULE_NAME + " =? ";
Cursor cursor = mDB.rawQuery(query, parameter);
cursor.moveToFirst();
while(!cursor.isAfterLast()){
if (cursor.getString(cursor.getColumnIndex(DatabaseContracts.Tables.CheckingDataOnServer.IS_ATTENDANCE_SAVED)).equals("false")){
mClassId = cursor.getString(cursor.getColumnIndex(DatabaseContracts.Tables.CheckingDataOnServer.CLASS_ID));
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
classAttendanceDate = cursor.getString(cursor.getColumnIndex(DatabaseContracts.Tables.CheckingDataOnServer.DATE));
Date attendancedate = null;
try {
attendancedate = dateFormat.parse(classAttendanceDate);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
date = format.format(attendancedate);
String[] parameters = {mClassId ,date + "%"};
Cursor studentInfo = mDB.rawQuery(" SELECT * FROM " + DatabaseContracts.Tables.AttendanceTable.TABLE +
" WHERE " + DatabaseContracts.Tables.AttendanceTable.CLASS_ID + " =? " +
" AND " + DatabaseContracts.Tables.AttendanceTable.ATTENDANCE_DATE + " LIKE ? ", parameters);
JSONObject attObj = new JSONObject();
try {
attObj.put(StudentsAttendanceContracts.FK_STAFF_ID, mStaffId);
attObj.put(StudentsAttendanceContracts.CLASS_ID, mClassId);
attObj.put(StudentsAttendanceContracts.ATTENDANCE_DATE, classAttendanceDate);
JSONArray studentArray = new JSONArray();
studentInfo.moveToFirst();
while (!studentInfo.isAfterLast())
{
JSONObject stuObj = new JSONObject();
stuObj.put(StudentsAttendanceContracts.STUDENT_ID, studentInfo.getString(studentInfo.getColumnIndex(DatabaseContracts.Tables.AttendanceTable.STUDENT_ID)));
stuObj.put(StudentsAttendanceContracts.ATTENDENCE_STATUS, studentInfo.getString(studentInfo.getColumnIndex(DatabaseContracts.Tables.AttendanceTable.ATTENDANCE_STATUS)));
studentArray.put(stuObj);
studentInfo.moveToNext();
}
attObj.put(StudentsAttendanceContracts.ATTENDANCE_KEY, studentArray);
AsyncWorkerEncrypted mAsyncWorker = new AsyncWorkerEncrypted(context,false);
mAsyncWorker.delegate = this;
mAsyncWorker.execute(ServerConnector.MARK_ATTENDANCE, attObj.toString(), RequestConstants.POST_REQUEST, RequestConstants.HEADER_YES, RequestConstants.MARK_ATTENDANCE);
} catch (JSONException e) {
e.printStackTrace();
}
}
cursor.moveToNext();
}
}
#Override
public void onRefresh() {
}
#Override
public void ReceivedResponseFromServer(String output, String REQUEST_NUMBER) {
switch (REQUEST_NUMBER) {
case RequestConstants.MARK_ATTENDANCE :
Boolean response = false ;
try {
JSONObject obj = new JSONObject(output);
response = obj.getBoolean(StudentsAttendanceContracts.RESPONSE_STATUS);
} catch (JSONException e) {
e.printStackTrace();
}
if(response){
String[] updateparameterOfCheckingPendingUpdatesTable = {"true", "Attendance", mClassId, date+"%"};
String Updatequery = " UPDATE " + DatabaseContracts.Tables.CheckingDataOnServer.TABLE + " SET " +
"" + DatabaseContracts.Tables.CheckingDataOnServer.IS_ATTENDANCE_SAVED + " =? " +
" WHERE " + DatabaseContracts.Tables.CheckingDataOnServer.MODULE_NAME + " =? " +
" AND " + DatabaseContracts.Tables.CheckingDataOnServer.CLASS_ID + " =? " +
" AND " + DatabaseContracts.Tables.CheckingDataOnServer.DATE + " LIKE ? " ;
mDB.execSQL(Updatequery, updateparameterOfCheckingPendingUpdatesTable);
stopService(new Intent(mContext, PendingUpdatesService.class)) ;
SharedPreferenceSingleton.getInstance().init(mContext);
SharedPreferenceSingleton.getInstance().writeIntPreference(StudentsAttendanceContracts.IF_ATTENDANCE_FAILED, 0);
}
break;
}
}
enter code here
stopService(new Intent(mContext, PendingUpdatesService.class)) ;
for this line i am getting null object reference for context ....
this is my stacktrace
06-03 12:55:43.051 7714-7714/com.synclovis.bluewingsstaff E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.synclovis.bluewingsstaff, PID: 7714
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Context.stopService(android.content.Intent)' on a null object reference
at android.content.ContextWrapper.stopService(ContextWrapper.java:539)
at com.synclovis.bluewingsstaff.util.MarkAttendance.ReceivedResponseFromServer(MarkAttendance.java:119)
at com.synclovis.bluewingsstaff.networkEngine.AsyncWorkerEncrypted.onPostExecute(AsyncWorkerEncrypted.java:178)
at com.synclovis.bluewingsstaff.networkEngine.AsyncWorkerEncrypted.onPostExecute(AsyncWorkerEncrypted.java:26)
at android.os.AsyncTask.finish(AsyncTask.java:636)
at android.os.AsyncTask.access$500(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6946)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Try replacing getApplicationContext() with this.
Please provide the stacktrace which appears in your logcat when the exception occurs.
You are calling the ReceivedResponseFromServer method from the Async task.
It looks like updateAttendance() is where you would prefer to set the context.
It's hard to tell if it's a threading issue or something else, but a quick fix should be just passing in the context from the async task if you have access to it. That way you need not set the context in updateAttendance() as you're not using it in that method anyway (unless you're using it elsewhere in the class).
after I update an object in my syncAdapter I can't get it back by id again. It seems that the id get lost after the update. What leaves behind is a null object.
Here's my source code how I update the object:
#Override
public void updateUserThread(Context ctxt, UserThread userThread, boolean notified)
{
try
{
ContentValues values = new ContentValues();
values.put(DBHandler.TOPIC, userThread.getTopic());
if(userThread.getCreationDate() != null)
values.put(DBHandler.USER_THREAD_CREATION_DATE, userThread.getCreationDate().getTime());
values.put(DBHandler.THREAD_TYPE, Helper.threadTypeToString(userThread.getThreadType()));
values.put(DBHandler.MEETING_PLACE, userThread.getMeetingPlace());
values.put(DBHandler.SUBJECT, userThread.getSubject());
values.put(DBHandler.SENT, Helper.convertBooleanToInt(userThread.isSent()));
if(userThread.getStartDate() != null)
values.put(DBHandler.START_DATE, userThread.getStartDate().getTime()); //Helper.getDateTime(
values.put(DBHandler.FOR_ALL, userThread.isForAll());
values.put(DBHandler.ID_SERVER, userThread.getIdServer());
if(userThread.getAuthor() != null)
values.put(DBHandler.ID_USER_FK, userThread.getAuthor().getIdUser());
if(notified)
{
ctxt.getContentResolver().update(TeamChannelProvider.USER_THREAD_URI, values, DBHandler.ID_USER_THREAD + "=" + "?", new String[]{String.valueOf(userThread.getIdUserThread())});
}
else
{
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
long status = db.update(TABLE_USER_THREAD, values, DBHandler.ID_USER_THREAD + "=?", new String[]{String.valueOf(userThread.getIdUserThread())});
db.setTransactionSuccessful();
db.endTransaction();
Log.i(Constants.TAG, "Status: " + status);
}
}
catch(Exception exc)
{
Log.e(Constants.TAG, "ERROR - DBHandlerTeamChannel -> updateUserThread", exc);
}
finally
{
Log.i(Constants.TAG, "UserThread updated with ID " + (notified ? "(notified) " : "not notified ") + userThread.getIdUserThread() + ", Server-ID: " + userThread.getIdServer());
}
}
So I'm trying to add validation onto my btnSubmit which will check that all editText fields have some sort of data in before storing into the array. Would anyone be able to help?
if (btnSubmit == null) throw new AssertionError();
btnSubmit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(editMod.getText().length()==0){
editMod.setError("Please fill in all fields");
}
else if(editRoom.getText().length()==0){
editRoom.setError("Please fill in all fields");
}
if (editMod.getText() != null) {
strModule = editMod.getText().toString();
}
if (editRoom.getText() != null) {
strRoomInfo = editMod.getText().toString();
}
inputData = strDay + " " + strTime + " " + strDuration + " " + strType + " " + strModule + " " + strRoomInfo;
parent.addItem(inputData);
try {
writeFile();
} catch (Exception e) {
Log.e("Writing to file Failed.", " ");
}
}
});
}
What's editMod here? EditText or TextInputLayout?
For this current code, here is the updated version:
if (btnSubmit == null) throw new AssertionError();
btnSubmit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(editMod.getText().toString().isEmpty()){
editMod.setError("Please fill in all fields");
}
else if(editRoom.getText().toString().isEmpty()){
editRoom.setError("Please fill in all fields");
}
if (editMod.getText().toString() != null) {
strModule = editMod.getText().toString();
}
if (editRoom.getText().toString() != null) {
strRoomInfo = editMod.getText().toString();
}
inputData = strDay + " " + strTime + " " + strDuration + " " + strType + " " + strModule + " " + strRoomInfo;
parent.addItem(inputData);
try {
writeFile();
} catch (Exception e) {
Log.e("Writing to file Failed.", " ");
}
}
});
}
Update your question and add xml code plus the rest of Java Code.
Try this code:
if (TextUtils.isEmtpy(<Your EditText here>.getText().toString())) {
//Empty
}
I created a compound view consisting of one TextView and one "Buy" Button.
For my compound view, I made a custom attribute called onBuyClick. It is supposed to serve the same purpose as the View's onClick attribute, but have the listener not on the whole view but only on the button. So, the first thing I did is copy from the View class what the onClick attribute does. And it worked! (with minor adaptations).
But as soon as I add btnBuy.setOnClickListener(new OnClickListener() {, it becomes unable to find the method I want it to get and throws IllegalStateException (The second one, where NoSuchMethodException is being caught).
Here is the piece that executed once the is an onBuyClick attribute:
if (context.isRestricted()) {
throw new IllegalStateException("The android:onClick attribute cannot "
+ "be used within a restricted context");
}
final String handlerName = a.getString(attr);
if (handlerName != null) {
btnBuy.setOnClickListener(new OnClickListener() { //As soon as "btnBuy." is added, everything crashes once the button is pressed.
private Method mHandler;
public void onClick(View v) {
if (mHandler == null) {
try {
mHandler = getContext().getClass().getMethod(handlerName,
View.class);
} catch (NoSuchMethodException e) {
int id = getId();
String idText = id == NO_ID ? "" : " with id '"
+ getContext().getResources().getResourceEntryName(
id) + "'";
throw new IllegalStateException("Could not find a method " +
handlerName + "(View) in the activity "
+ getContext().getClass() + " for onClick handler"
+ " on view " + this.getClass() + idText, e);
}
}
try {
mHandler.invoke(getContext(), this);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not execute non "
+ "public method of the activity", e);
} catch (InvocationTargetException e) {
throw new IllegalStateException("Could not execute "
+ "method of the activity", e);
}
}
});
}
and here are the variables defined outside this piece: btnBuy, the "Buy" Button in my compound view, and a is a TypedArray containing all my attributes.
Can someone please help me?
I have an IntentService that goes connects to a website and creates a list with parsed HTML via JSoup. I now need to pass that list back in a Bundle and I'm not sure how to do it. Here is my code for the IntentService:
public class NewerService extends IntentService {
public NewerService() {
super("NewerService");
// TODO Auto-generated constructor stub
}
#Override
protected void onHandleIntent(Intent intent) {
ResultReceiver rec = intent.getParcelableExtra("receiverTag");
String playersName = intent.getStringExtra("Player");
List<String> list = new ArrayList<String>();
Document doc = null;
try {
doc = Jsoup.connect("http://espn.go.com/nhl/team/stats/_/name/phi/philadelphia-flyers").get();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Element table : doc.select("table.tablehead")) {
for (Element row : table.select("tr")) {
Elements tds = row.select("td");
if (tds.size() > 6) {
String a = tds.get(0).text() + ":" + " Games Played: "+
tds.get(1).text()+"," + " GOALS: " + tds.get(2).text()+"," +
" ASSISTS: " + tds.get(3).text() + " POINTS: " +
tds.get(4).text() + " PLUS/MINUS: " + tds.get(5).text() + "
PIM: " + tds.get(6).text();
list.add(a); // Add the string to the list
}
}
}
}
I appreciate any help in advance. Thank you
Have you tried using Bundle.putStringArrayList or Intent.putStringArrayListExtra?
If you mean you don't know how to start an activity from a service, try this question.