Basically I have a stand alone class, which does not use Activity OR Service.
A function in the class starts a new Authenticator.
I have a string in the strings.xml file, which I want to access
Looking for the best method
Example code
class MyConnection(){
String username;
String pwd;
String strurl;
public MyConnection(String usernameIN, String pwdIN, String urlIN){
this.username = usernameIN;
this.pwd = pwdIN;
this.strurl = urlIN
}
public void
URL url = null;
try {
url = new URL(this.strURL);
URLConnection urlConn = null;
Authenticator.setDefault(new Authenticator()){
protected PasswordAuthentication getPasswordAuthentication()(
// I want my vars from strings.xml here
return new PasswordAuthentication(strUsername, strPwd.toCharArray());
}
});
urlCOnn = url.openConnection();
//Rest of the code, including CATCH
}
I passed the vars through into the class BUT how do I access them When I set the PasswordAuthentication. OR Can I access them direct from strings.xml ???
How do you create an instance of the MyConnection class?
It should be through an Activity or a Service, right?
Then when you create it, pass the current Activity
public class MyConnection {
private Activity activity;
public MyConnection(Activity a) {
this.activity = a;
}
//....
private void method() {
activity.getResources().getString(R.string....);
}
}
edit: I did not see you already had a constructor. Then add a parameter to the existing one.
You can add a final modificator to your MyConnection() constructor's parameters, this way you can use them as parameters in the call to PasswordAuthentication(). Hope this helps.
You'll need to pass a Context instance to your class or individual methods. The Context instance can be an instance of Activity or Service or anything else which is a subclass of Context. You can then use this to access system resources:
class MyConnection
{
private final Context context;
public MyConnection( Context context )
{
this.context = context;
}
.
.
.
public void someMethod()
{
String str = context.getResources().getString ( R.string.myString );
}
}
Related
This is NetworkUtils.class
public class NetworkUtils {
final static String GITHUB_BASE_URL =
"https://api.github.com/search/repositories";
final static String PARAM_QUERY = "q";
final static String PARAM_SORT = "sort";
final static String sortBy = "stars";
public static URL buildUrl(String githubSearchQuery) {
Uri builtUri = Uri.parse(GITHUB_BASE_URL).buildUpon()
.appendQueryParameter(PARAM_QUERY, githubSearchQuery)
.appendQueryParameter(PARAM_SORT, sortBy)
.build();
URL url = null;
try {
url = new URL(builtUri.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
}
return url;
}
This is MainActivity.class
public class MainActivity extends AppCompatActivity {
private EditText mSearchBoxEditText;
private TextView mUrlDisplayTextView;
private TextView mSearchResultsTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSearchBoxEditText = (EditText) findViewById(R.id.et_search_box);
mUrlDisplayTextView = (TextView) findViewById(R.id.tv_url_display);
mSearchResultsTextView = (TextView) findViewById(R.id.tv_github_search_results_json);
}
private void makeGithubSearchQuery() {
String githubQuery = mSearchBoxEditText.getText().toString();
URL githubSearchUrl = NetworkUtils.buildUrl(githubQuery)
mUrlDisplayTextView.setText(githubSearchUrl.toString());
String githubSearchResults = null;
try {
githubSearchResults = NetworkUtils.getResponseFromHttpUrl(githubSearchUrl);
mSearchResultsTextView.setText(githubSearchResults);
} catch (IOException e) {
e.printStackTrace();
}
// TODO (4) Create a new GithubQueryTask and call its execute method, passing in the url to query
}
Notice that MainActivity.class uses this code.
URL githubSearchUrl = NetworkUtils.buildUrl(githubQuery)
and the NetworkUtils.class uses this code.
public static URL buildUrl(String githubSearchQuery)
I do believe that
NetworkUtils.buildUrl(githubQuery) is referring to buildUrl(String githubSearchQuery) and it is really confusing. I understand that the value of githubQuery will be the input from mSearchBoxEditText.getText().toString();, and now I'm wondering what would be the value of String githubSearchQuery, where would it come from??
2 Java Class Using Same Method With Differences
Actually the title itself is a huge mistake.
They are not same method with differences. The one you can find in NetworkUtils is the actual definition of the method. In MainActivity, You are just invoking it.
When you calls a method, the the control goes to the definition. Also a copy of arguments are passed to it(Note that in case of objects, a copy of the reference is passed, not a copy of the actual object. So any change affects in both sides). From the definition part, you can access it with a the new name.
but isnt that githubQuery is in private class?
It is not private. It is a local, means it has lesser scope than private. However, it isn't going to be a problem as long as you have a reference.
The value of githubSearchQuery will be the same as githubQuery as its being used to call buildUrl(String githubSearchQuery) method.
I have an application where I want to search for a book using ISBN and display it on the screen. The Book objects are stored in a Realm database with ISBN as primary key. If they are not stored in the database, they are retrieved asynchronously (ASyncTask) from a server and then stored in the database.
Now, I am unfamiliar with Realm and how to use it.
In the code below, would ViewBookActivity and MainController run on the same thread, and therefore use the same database instance? Would returning a Realm object from a "static class" be a problem?
How can I guarantee that calling MainController.getBook() always returns a book? The way it works now, is that when getBook is called and the book is not in the database, it returns null.
Is a changelisteners in each Activity that uses the MainController the only way? I want to avoid, if possible, to use/reference Realm at all in the activities and make them get objects through the MainController instead.
public class RealmActivity extends Activity {
private Realm realm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this).build();
Realm.deleteRealm(realmConfiguration); // Clean slate
Realm.setDefaultConfiguration(realmConfiguration); // Make this Realm the default
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
public class ViewBookActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
ISBN = intent.getStringExtra("ISBN");
setContentView(R.layout.activity_scan_result);
setBook(ISBN);
}
public void setBook(String ISBN) {
Book b = MainController.getBook(ISBN);
// Display book on screen
}
}
public class MainController {
static Realm realm = Realm.getDefaultInstance();
public static Book getBook(String isbn) {
Book book = realm.where(Book.class)
.equalTo("isbn", isbn)
.findFirst();
if (book == null) {
NetworkController.getBook(isbn);
} else {
return book;
}
return null;
}
}
public class NetworkController {
private static BookHandler bookHandler = new BookHandler();
public static void getBook(String isbn) {
NetworkHelper.sendRequest(HTTPRequestMethod.GET,
"/books/" + isbn, bookHandler);
}
}
public class NetworkHelper {
private static String host = "http://crowdshelf-dev.herokuapp.com";
public static void sendRequest(final HTTPRequestMethod requestMethod, final String route, final ResponseHandler responseHandler) {
new AsyncTask<Void, Void, Void>() {
#Override
protected void doInBackground(Void... params) {
try {
URL url = new URL(host + "/api" + route);
Log.d("NETDBTEST", "NetworkHelper request: " + requestMethod.toString() + " URL: " + url.toString());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
BufferedReader bReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = bReader.readLine()) != null) {
builder.append(line).append("\n");
}
String jsonString = builder.toString();
responseHandler.handleJsonResponse(jsonString);
return null;
}
}
}.execute();
}
}
public class BookHandler implements ResponseHandler {
#Override
public void handleJsonResponse(String jsonString) {
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
realm.createOrUpdateObjectFromJson(Book.class, jsonString);
realm.commitTransaction();
realm.close();
}
}
public class Book extends RealmObject{
#PrimaryKey
private String isbn;
// Other fields, getters and setters
}
1) First, I don't know why you created RealmActivity just for cleaning database. Activities are for showing UI. If it doesn't have any purpose then move the code to some other class. Like you can create a new class RealmHandler and keep this kind of code there.
2) You don't really need to create a static function to get Realm object. You could have your MainController function like this:
public class MainController {
public Book getBook(String isbn, Context context) {
Realm realm = Realm.getDefaultInstance(context);
Book book = realm.where(Book.class)
.equalTo("isbn", isbn)
.findFirst();
if (book == null) {
NetworkController.getBook(isbn);
} else {
return book;
}
return null;
}
}
3)
How can I guarantee that calling MainController.getBook() always
returns a book?
You can't guarantee that you always get a Book, for example a Book isn't found on server, or there's no internet connection. You have to handle that case manually.
sendBook function calls AsyncTask and AsyncTask runs on a separate thread so you can't return your server results when you call NetworkController.getBook(isbn). The only way to get results is in BookHandler. handleJsonResponse
By the way, you don't need to implement Handler to get results from AsyncTask. You can override onPostExecution function to get control of your results and perform UI on Main thread.
Solution:
You can handle this in different ways as you like, here's one of the way:
i) Call MainController.getBook() to get a book. If Book isn't found then run NetworkController.getBook(isbn); - This will run on a different Thread and current Thread will send back null to your Activity. If null then you just ignore it or perform action accordingly.
ii) In AsyncTask you could first show a ProgressBar to tell user something is in Process while you are getting data from Server. You could do this in onPreExecution function of AsyncTask.
iii) Get results in onPostExecution function of AsyncTask. Now you are back on your main thread. You can directly update your UI if you are in the same Activity, but in your case you are not. You can't directly return data like in a function or update UI.
iv) You can send a signal to your MainActivity that network call has finished and new data is in the database so update view. You can could use Event bus for this purpose. I personally use Otto by Square: http://square.github.io/otto/
I am trying to make social network application for Android. My question is how to maintain user session when user logs in?
Please help me to find the solution for the above question.
try
public class Session {
private static String sessionId;
private static String userRole;
public static void setSessionId(String sessionId) {
Session.sessionId = sessionId;
}
public static String getSessionId() {
return sessionId;
}
}
Use this class and import it in every other activity. You can define your own functions to maintain your specific session data
http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/
Please look at the above link. It is detailed pretty well.
Use a singleton to maintain the user session.
I use DefaultHttpClient with HttpRequestInterceptor and HttpResponseInterceptor.
Something similar to this:
public class HTTPClients {
private static DefaultHttpClient _defaultClient;
private static String session_id;
private static HTTPClients _me;
private HTTPClients() {
}
public static DefaultHttpClient getDefaultHttpClient(){
if ( _defaultClient == null ) {
_defaultClient = new DefaultHttpClient();
_me = new HTTPClients();
_defaultClient.addResponseInterceptor(_me.new SessionKeeper());
_defaultClient.addRequestInterceptor(_me.new SessionAdder());
}
return _defaultClient;
}
private class SessionAdder implements HttpRequestInterceptor {
#Override
public void process(HttpRequest request, HttpContext context)
throws HttpException, IOException {
Log.d("SessionKeeper", "Adding session with the following string: " + session_id);
if ( session_id != null ) {
request.setHeader("Cookie", session_id);
}
}
}
private class SessionKeeper implements HttpResponseInterceptor {
#Override
public void process(HttpResponse response, HttpContext context)
throws HttpException, IOException {
Header[] headers = response.getHeaders("Set-Cookie");
if ( headers != null && headers.length == 1 ){
Log.d("SessionKeeper", "Keeping session with the following string: " + headers[0].getValue());
session_id = headers[0].getValue();
}
}
}
}
I have the similar problem on my android client side when I am trying to send that session id ,the server side is creating a new session...but what you check at android client side that you are not creating the DefaulthttpClient twice... create the httpclient just once say main activity and pass the objects in other activity ...... dont create second HttpClient
Create session using SharedPreferences.
public class Session {
private SharedPreferences prefs;
public Session(Context cntx) {
// TODO Auto-generated constructor stub
prefs = PreferenceManager.getDefaultSharedPreferences(cntx);
}
public void setusename(String usename) {
prefs.edit().putString("usename", usename).commit();
}
public String getusename() {
String usename = prefs.getString("usename","");
return usename;
}
}
now after making this class when u want to use this use like this make object og this class like
private Session session;//global variable
session = new Session(cntx); //in oncreate
//and now we set sharedpreference then use this like
session.setusename("USERNAME");
now when ever u want to get username then same work for session object and call this
session.getusename();
best of luck :) same for password
I got this following method in an non Activity class, My code is below.
public class ReadTextByLineNo {
public void setContext(Context _context) {
if (context == null) {
context = _context;
}
}
public String getTextByLine(int Filename,int LineNumber)
{
String output="";
String line="";
int counter=1;
try
{
InputStream in = context.getResources().openRawResource(Filename);
//InputStream in = assetManager.open(Filename);
if(in!=null)
{
InputStreamReader input = new InputStreamReader(in);
BufferedReader buff = new BufferedReader(input);
while((line=buff.readLine())!=null)
{
if(counter ==LineNumber){
output=line;
}counter++;
}in.close();
}else{
Log.e("Input STREAM PROBLEM", "TEXT IS NULL NULL NULL NULL NULL");
}
}catch(Exception e)
{
//log
}
return output;
}
**I am calling this method from an NON_ACTIVITY CLASS LIKE THIS **
class sample implements Isample
{
ReadTextByLineNo read = new ReadTextByLineNo();
String subMsg = read.getTextByLine(R.raw.subtitle, storySceneId);
//the above string is to called from an activity called Layout
}
How do I use resources/context from an non activity class? I cannot use the context in constructor since I'm also calling the method from an non Activity class.
so I can't set read.setContent(this); where I got setContext method in my ReadtextByLineNo class, thanks for the help .
Please help me to get the context/resourse in the class sample and example by code is appreciated
public class ReadTextByLineNo {
private static Context context;
public static void setContext(Context mcontext) {
if (context == null)
context = mcontext;
}
}
when your application start, just initialize this context, by calling
ReadTextByLineNo.setContext(getApplicationContext());
from your main activity..
Enjoy...
I'm writing an application that validates login credentials on an external webserver - so I have the basic issue of creating a login screen that when submitted will send an HTTP request to a server in the background and not cause the UI to hang - whilst providing a ProgressDialog to the user.
My problem lies in, I want to write a generic HTTP Request class that extends AsyncTask, so when I call .execute() I will then pass String parameters which may contain something like 'post', and when doInBackground is called this will see the 'post' string and then forward those parameters onto the respective call in my class. Pseudo code would be something like
public class HTTPOperations extends AsyncTask<String, Void, String>
{
doInBackground(String... string1,additionalParams)
{
if string1.equals "post"
response = httpPost(additionalParams)
return response;
}
httpPost(params)
{
// do http post request
}
}
This is all I could think of, other than creating a class for every HTTP Post/GET etc request I wish to make and extending ASyncTask...
Which leads me to my next problem, if the HTTP POST is successful and it returns an authentication token, how do I access this token?
Because new httpOperations.execute(), does not return the string from doInBackground, but a value of type
Sorry if this doesn't make sense, I can't figure this out at all. Please ask for elaboration if you need it. AsyncTask design patterns and ideas are hugely welcomed.
If you are designing a reusable task for something like this, you need to identify a reusable return type. Its a design decision on your part. Ask yourself, "Are my HTTP operations similar in both the mechanisms with which they are called and in which their data is processed?" If so, you can design a single class to do both. If not, you probably need different classes for your different remote operations.
In my personal use, I have an object i attach key value pairs to and the common return type is the HttpEntity. This is the return type for both HTTP Get and Post, and this seems to work ok in my scenarios because i throw exceptions in exceptional HTTP result situations, like 404. Another nice aspect of this setup is that the code to attach parameters to a get or post are fairly similar, so this logic is pretty easy to construct.
An example would be something like this (psuedo):
public interface DownloadCallback {
void onSuccess(String downloadedString);
void onFailure(Exception exception);
}
Then in your code, where you go to do the download:
DownloadCallback dc = new DownloadCallback(){
public void onSuccess(String downloadedString){
Log.d("TEST", "Downloaded the string: "+ downloadedString);
}
public void onFailure(Exception e){
Log.d("TEST", "Download had a serious failure: "+ e.getMessage());
}
}
DownloadAsyncTask dlTask = new DownloadAsyncTask(dc);
Then inside the constructor of DownloadAsyncTask, store the DownloadCallback and, when the download is complete or fails, call the method on the download callback that corresponds to the event. So...
public class DownloadAsyncTask extends AsyncTask <X, Y, Z>(){
DownloadCallback dc = null;
DownloadAsyncTask(DownloadCallback dc){
this.dc = dc;
}
... other stuff ...
protected void onPostExecute(String string){
dc.onSuccess(string);
}
}
I'm going to reiterate that I think for the good of yourself, you should pass back HttpEntities. String may seem like a good idea now, but it really leads to trouble later when you want to do more sophisticated logic behind your http calls. Of course, thats up to you. Hopefully this helps.
suppose the data format with web api is json, my design pattern :
common classes
1.MyAsyncTask : extends AsyncTask
2.BackgroundBase : parameters to server
3.API_Base : parameters from server
4.MyTaskCompleted : callback interface
public class MyAsyncTask<BackgroundClass extends BackgroundBase,APIClass extends API_Base> extends AsyncTask<BackgroundClass, Void, APIClass> {
private ProgressDialog pd ;
private MyTaskCompleted listener;
private Context cxt;
private Class<APIClass> resultType;
private String url;
private int requestCode;
public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url){
this.listener = listener;
this.cxt = (Context)listener;
this.requestCode = requestCode;
this.resultType = resultType;
this.url = url;
}
public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url, ProgressDialog pd){
this(listener, resultType, requestCode, url);
this.pd = pd;
this.pd.show();
}
#Override
protected APIClass doInBackground(BackgroundClass... params) {
APIClass result = null;
try {
//do something with url and params, and get data from WebServer api
BackgroundClass oParams = params[0];
String sUrl = url + "?d=" + URLEncoder.encode(oParams.getJSON(), "UTF-8");
String source = "{\"RtnCode\":1, \"ResultA\":\"result aaa\", \"ResultB\":\"result bbb\"}";
//to see progressdialog
Thread.sleep(2000);
result = new com.google.gson.Gson().fromJson(source, resultType);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(APIClass result) {
super.onPostExecute(result);
try {
if(pd != null && pd.isShowing())
pd.dismiss();
API_Base oApi_Base = (API_Base)result;
listener.onMyTaskCompleted(result , this.requestCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class API_Base {
public int RtnCode;
public String getJSON(Context context) throws Exception
{
return new com.google.gson.Gson().toJson(this);
}
public String toString(){
StringBuilder sb = new StringBuilder();
for (Field field : this.getClass().getFields()) {
try {
field.setAccessible(true);
Object value = field.get(this);
if (value != null) {
sb.append(String.format("%s = %s\n", field.getName(), value));
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
return sb.toString();
}
}
public class BackgroundBase {
public String getJSON() throws Exception
{
return new com.google.gson.Gson().toJson(this);
}
}
public interface MyTaskCompleted {
void onMyTaskCompleted(API_Base oApi_Base, int requestCode) ;
}
example, let's call two api in one activity
assume :
API 1.http://www.google.com/action/a
input params : ActionA
output params : RtnCode, ResultA
API 2.http://www.google.com/action/b
input params : ActionB
output params : RtnCode, ResultB
classes with example :
1.MyActivity : extends Activity and implements MyTaskCompleted
2.MyConfig : utility class, i set requestCode here
3.BackgroundActionA, BackgroundActionB : model classes for api's input params
4.API_ActionA, API_ActionB : model classes for api's output params
public class MyActivity extends Activity implements MyTaskCompleted {
ProgressDialog pd;
Button btnActionA, btnActionB;
TextView txtResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
btnActionA = (Button)findViewById(R.id.btn_actionA);
btnActionB = (Button)findViewById(R.id.btn_actionB);
txtResult = (TextView)findViewById(R.id.txt_result);
btnActionA.setOnClickListener(listener_ActionA);
btnActionB.setOnClickListener(listener_ActionB);
pd = new ProgressDialog(MyActivity.this);
pd.setTitle("Title");
pd.setMessage("Loading");
}
Button.OnClickListener listener_ActionA = new Button.OnClickListener(){
#Override
public void onClick(View v) {
//without ProgressDialog
BackgroundActionA oBackgroundActionA = new BackgroundActionA("AAA");
new MyAsyncTask<BackgroundActionA, API_ActionA>(MyActivity.this,
API_ActionA.class,
MyConfig.RequestCode_actionA,
"http://www.google.com/action/a").execute(oBackgroundActionA);
}
};
Button.OnClickListener listener_ActionB = new Button.OnClickListener(){
#Override
public void onClick(View v) {
//has ProgressDialog
BackgroundActionB oBackgroundActionB = new BackgroundActionB("BBB");
new MyAsyncTask<BackgroundActionB, API_ActionB>(MyActivity.this,
API_ActionB.class,
MyConfig.RequestCode_actionB,
"http://www.google.com/action/b",
MyActivity.this.pd).execute(oBackgroundActionB);
}
};
#Override
public void onMyTaskCompleted(API_Base oApi_Base, int requestCode) {
// TODO Auto-generated method stub
if(requestCode == MyConfig.RequestCode_actionA){
API_ActionA oAPI_ActionA = (API_ActionA)oApi_Base;
txtResult.setText(oAPI_ActionA.toString());
}else if(requestCode == MyConfig.RequestCode_actionB){
API_ActionB oAPI_ActionB = (API_ActionB)oApi_Base;
txtResult.setText(oAPI_ActionB.toString());
}
}
}
public class MyConfig {
public static String LogTag = "henrytest";
public static int RequestCode_actionA = 1001;
public static int RequestCode_actionB = 1002;
}
public class BackgroundActionA extends BackgroundBase {
public String ActionA ;
public BackgroundActionA(String actionA){
this.ActionA = actionA;
}
}
public class BackgroundActionB extends BackgroundBase {
public String ActionB;
public BackgroundActionB(String actionB){
this.ActionB = actionB;
}
}
public class API_ActionA extends API_Base {
public String ResultA;
}
public class API_ActionB extends API_Base {
public String ResultB;
}
Advantage with this design pattern :
1.one Advantage for multi api
2.just add model classes for new api, ex: BackgroundActionA and API_ActionA
3.determine which API by different requestCode in callback function : onMyTaskCompleted