A Java Class Invoking A Method - android

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.

Related

How to run AsyncTask in Android?

I previously wrote a simple currency converter program, that fetches real time rate conversion via an exchange rate API. The full code is available here: https://github.com/LaChope/expenses-robot
I want know to reuse most of this code to build an Android app, but I am really not familiar with AsyncTask and do know how to implement it (I need it for the GET requests).
Here is what I've implemented so far, but I am not sure it is the correct way to proceed.
My Converter class:
public class Converter extends AsyncTask<Void, Void, Float> {
private final RestTemplate restTemplate = new RestTemplate();
private final EditText baseCurrency;
private final EditText targetCurrency;
private final EditText amount;
public Converter(EditText baseCurrency, EditText targetCurrency, EditText amount) {
this.baseCurrency = baseCurrency;
this.targetCurrency = targetCurrency;
this.amount = amount;
}
#Override
protected Float doInBackground(Void... voids) {
String url = "https://api.exchangeratesapi.io/latest?" + baseCurrency;
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = null;
try {
root = mapper.readTree(responseEntity.getBody());
} catch (IOException e) {
e.printStackTrace();
}
String rates1 = "rates";
JsonNode name = root.get(rates1);
JsonNode rates = name.get(String.valueOf(targetCurrency));
float rate = rates.floatValue();
return rate;
}
#Override
protected void onPostExecute(Float rate) {
super.onPostExecute(rate);
output.setText();
return;
}
}
My MainActivity class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void displayResult(View view) {
EditText textBaseCurrency = (EditText) findViewById(R.id.base_currency);
EditText textTargetCurrency = (EditText) findViewById(R.id.target_currency);
EditText textAmount = (EditText) findViewById(R.id.amount);
TextView output = (TextView) findViewById(R.id.result);
output.setInputType(InputType.TYPE_CLASS_NUMBER);
Converter converter = new Converter(textBaseCurrency, textTargetCurrency, textAmount);
output.setText();
}
}
How to communicate the output of my conversion made in the Converter class to the MainActivity to display it?
Initialize AsyncTask as
Converter converter = new Converter(textBaseCurrency, textTargetCurrency, textAmount);
converter.execute();
Then the code in AsyncTask will start executing.
Assign output.setText(); in onPostExecute(Float rate) {}.

What context should I pass to read from assets from another java class?

I have 2 Java files (CreateMyDb.java,ReadfromAssets.java).
In ReadfromAssets.java, I have the code below.
If I want to call ReadFileFromAssets method from CreateMyDb.java, How should I call,What is the context param I should pass? I am trying it make it work but in vain.
Thanks
public class ReadFromAssets extends Activity {
private static final String splitBy = ",";
private static int ID_Count = 6;
private static final String ObjName = "Question";
private static String NewObjName = "";
public void ReadFileFromAssets(Context myContext) {
//read from assets
myContext.getAssets();
AssetManager assetManager = myContext.getAssets();
InputStreamReader is = null;
try {
is = new InputStreamReader(assetManager.open("questions.csv"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BufferedReader reader = new BufferedReader(is);
try {
reader.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String line;
try {
while ((line = reader.readLine()) != null) {
NewObjName = ObjName+ID_Count;
String[] QDetails = line.split(splitBy);
Question NewObjName=new Question(QDetails[0],QDetails[1],QDetails[2],QDetails[3],QDetails[4],QDetails[5], QDetails[6]);
CreateMyDb db=new CreateMyDb (this);
db.AddToDB(NewObjName);
ID_Count = ID_Count+1;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//use assets however
}
}
In the CreateMyDb.java file, I am calling the same method as ,
private void addQuestions(){
ReadFromAssets ReadCsv = new ReadFromAssets();
ReadCsv.ReadFileFromAssets();//what should I pass as context here?
}
pass the context of that class where you are accessing this class method
ReadCsv.ReadFileFromAssets(CreateMyDb.this);
if the CreateMyDb class extend from activity or fragementactivity it obviously have the context of that activity too so pass the context of the class where you are accessing this thank you may be its help you
The most inmediate solution is pass the context of your activity to this class. Is that possible?
If you don't want to pass parameters, you can create an Application class to get the context of the application wherever you want.
public class ApplicationClass extends Application
{
private static ApplicationClass myAppClass;
#Override
public void onCreate()
{
super.onCreate();
myAppClass = this;
}
public static ApplicationClass getMyAppClass()
{
return myAppClass;
}
}
Then you must add the next line in the ManifestFile under the label
android:name="com.yourapp.ApplicationClass"
Now, you can call in you method ApplicationClass.getMyAppCLass().getAssets() without passing any context.
I must say that in this case the Application class is not used in the correct way. This class type is used to keep the application state, but is the only way I can think to do what you want without passing any parameter.

How to use managedQuery from an asyncTask

I am trying to make an Android music player. To make things easier, I have decided to copy the Artists on the phone to a local DB and then make some custom queries to the local data. I know how to copy the managedQuery to a db, but cannot do so on an AsyncTask since managedQuery is only accessible by an Activity class. I am trying to do this call in my Application class upon app startup. Does anyone know a way to call managedQuery inside of the AsyncTask? I really do not want to do this in my first activity that is called since it will slow my load speed significantly.
This is what I would like to do, although I know this will not compile...
public class AplayApplication extends Application implements
OnSharedPreferenceChangeListener {
private static final String TAG = AplayApplication.class.getSimpleName();
private SharedPreferences prefs;
protected MusicData musicData;
protected PlayerHandler mMediaPlayer;
protected boolean isPlaying;
private boolean prefUseDefaultShuffle;
private boolean prefUseSmartShuffle;
private int prefArtistSkipDuration;
private int prefUnheardArtistPct;
protected TabHost tabHost;
protected Song currentSong;
protected int currentSongPosition;
private static final String PREFERENCE_KEY = "seekBarPreference";
protected boolean hasLoadedSongs;
private static AplayApplication aplayapp;
#Override
public void onCreate() {
super.onCreate();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
setPrefs();
Log.i(TAG, "Application started");
mMediaPlayer = new PlayerHandler();
// code in question below this line
musicData = new MusicData(this); // this creates instance of database helper to access db
// will call execute on async task here.
// new getArtist().execute();
}
private class getArtists extends AsyncTask<Void, Void, Boolean>{
Cursor artCursor;
#Override
protected Boolean doInBackground(Void... params) {
String[] proj = {
MediaStore.Audio.Artists._ID,MediaStore.Audio.Artists.ARTIST,
};
artCursor = managedQuery(
MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, proj, null,
null, MediaStore.Audio.Artists.ARTIST + " ASC");
ContentValues values = new ContentValues();
artCursor.moveToPosition(-1);
while (artCursor.moveToNext()) {
values.put(
MusicData.S_DISPLAY,
newMusicCursor.getString(newMusicCursor
.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)));
values.put(MusicData.S_ARTIST, newMusicCursor
.getString(newMusicCursor
.getColumnIndex(MediaStore.Audio.Media.ARTIST)));
values.put(MusicData.S_FILE, newMusicCursor
.getString(newMusicCursor
.getColumnIndex(MediaStore.Audio.Media.DATA)));
this.musicData.insertMastSong(values);
}
return true;
}
//// code continues.....
As Sparky says, you could use CursorLoader instead of managedQuery.
If you are developing for sdk 8 you need to add Support Package to your project.
To avoid delay your application start maybe you could use a Service.
This is a little example for use a service, get the data from an url and then insert it to the database
public class GetArticlesService extends IntentService {
private static final String TAG = "GetArticlesService";
public GetArticlesService() {
super("GetdArticlesService");
}
/* (non-Javadoc)
* #see android.app.IntentService#onHandleIntent(android.content.Intent)
*/
#Override
protected void onHandleIntent(Intent intent) {
String url = "http://example.com/artists.json";
String response = null;
try {
response = Utils.httpPost(getApplicationContext(), url + "/api/GetArticles", null);
} catch (HttpHostConnectException e) {
e.printStackTrace();
}
if(!TextUtils.isEmpty(response)){
try {
JSONArray list = new JSONArray(response);
if(list.length() > 0){
ContentValues toInsert = new ContentValues[];
JSONObject art = null;
int cant = list.length();
for(int i = 0;i< cant; i++){
toInsert.clear();
art = list.getJSONObject(i);
toInsert = new ContentValues();
toInsert.put(Articles._ID, art.getInt("id"));
toInsert.put(Articles.DESCRIPTION, art.getString("description"));
toInsert.put(Articles.BARCODE, art.getString("barcode"));
toInsert.put(Articles.RUBRO, art.getString("rubro"));
toInsert.put(Articles.CLAVE, art.getString("clave"));
getContentResolver().inert(Articles.CONTENT_URI, toInsert);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
managedQuery is deprecated. Use CursorLoader instead.

Getting string in Protected Function Android

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 );
}
}

AsyncTask Android - Design Pattern and Return Values

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

Categories

Resources