I am new to Android programming.
Basically what I want to do is write a class that extends Activity and then use it in another class that also extends Activity.
In my case what I wanted to do was to be able use GsmCellLocation class members without having to initialise TelephonyManager.
So I created a class named as CellInformation and here is the content:
public class CellInformation extends Activity {
private TelephonyManager tm;
private GsmCellLocation cellLoc;
public CellInformation() {
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
cellLoc = (GsmCellLocation) tm.getCellLocation();
}
public GsmCellLocation updateCellInfo() {
cellLoc = (GsmCellLocation) tm.getCellLocation();
return cellLoc;
}
public int getCid() {
return (cellLoc.getCid()%65536);
}
public int getLac() {
return cellLoc.getLac();
}
public int getPsc() {
return cellLoc.getPsc();
}
}
and within my main activity this is how I initialise it:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
cell = new CellInformation();
}
I am getting System services not available to Activities before onCreate() error. If I was not meant to initialise it within onCreate, then where should I initialise it?
If my logic is completely wrong and/or this is not Android standard, how can I fix it?
Simply Don't extend the Activity until it is required. I saw the class CellInformation where Activity class not required. Remove it and it will solve your problem.
public class CellInformation {
..... // Method and Attributes.
private Context context;
CellInformation(Context context) {
this.context = context;
tm = (TelephonyManager)this.context.getSystemService(Context.TELEPHONY_SERVICE);
}
}
In Activity make the object of this class like :-
cell = new CellInformation(this);
Now, Make the object of this class in the activity where your require then call the method of this CellInformation.
Related
I have created an volley list in this i have problem to get data from adapter to activity and this activity to another activity. I have received error cannot cast activity.java to anotherActivity.java below is my code. Please help me anyone thanks.
My Interface itemclick in Adapter class
private OnItemClickGetPlaylist mListener;
public interface OnItemClickGetPlaylist{
public void OnPlaylistItemClick(String playlistName,int numOfItems,String imageViewForPlaylist);
}
public void setOnClickListenerOnPlaylist(OnItemClickGetPlaylist listener)
{
mListener = listener;
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id = playlist.getId_playlist_identify();
String PlaylistName = playlist.getTitile_of_playlist();
String imageOfPlaylist = playlist.getImage_of_playlist();
int numOfPlaylistSongs = getItemCount();
SendIdToDatabase(id);
if (mListener != null)
{
mListener.OnPlaylistItemClick(PlaylistName,numOfPlaylistSongs,imageOfPlaylist);
}
else {
Toast.makeText(context, "mListeren is null" + mListener, Toast.LENGTH_SHORT).show();
}
}
});
After get data handle OnPlaylistItemClick click in Activity below Codes
public void OnItemClickHandleInPlaylistActivity(String playlistName,int numOfItems,String imageViewForPlaylist)
{
//here is the adapter item click in activity now i want to send that data to another activity without any intent please help me.
// i have implement below code but it give me cannot cast activity to another activity error.
((anotherActivity) getApplicationContext()).OnItemClickInMusicActivity(playlistName,numOfItems,imageViewForPlaylist);
}
See the solution at https://stackoverflow.com/a/47637313/2413303
public class MyApplication extends Application {
private static MyApplication INSTANCE;
DataRepository dataRepository; // this is YOUR class
#Override
public void onCreate() {
super.onCreate();
INSTANCE = this;
dataRepository = new DataRepository();
}
public static MyApplication get() {
return INSTANCE;
}
}
The DataRepository should expose LiveData:
public class DataRepository {
private final MutableLiveData<MyData> data = new MutableLiveData<>();
public LiveData<MyData> getMyData() {
return data;
}
public void updateText(String text) {
MyData newData = data.getValue()
.toBuilder() // immutable new copy
.setText(text)
.build();
data.setValue(newData);
}
}
Where the Activity subscribes to this:
public class MyActivity extends AppCompatActivity {
DataRepository dataRepository;
TextView textView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApplication app = (MyApplication)getApplicationContext();
dataRepository = app.getDataRepository();
setContentView(R.layout.main_activity);
textView = findViewById(R.id.textview);
dataRepository.getMyData().observe(this, new Observer() {
#Override
public void onChange(MyObject myObject) {
textView.setText(myObject.getText());
}
}
}
So to update this text, you need to get the DataRepository class, and call updateText on it:
DataRepository dataRepository = MyApplication.get().dataRepository();
dataRepository.updateText("my new text");
Make sure that the data in DataRepository is properly persisted somewhere, or at least can be obtained again after process death. You might want to use a database for example (but not shared preferences).
If you don't want to use Intents, maybe you can use a publish/subscribe architecture. There is a library called eventbus (org.greenrobot:eventbus) very easy to use which could achieve what you want.
Use an Application Class instead.
public class MyApplicationClass extends Application{
#Override
public void onCreate() {
super.onCreate();
///do something on create
}
getterMethods(){...}
setterMethods(){...}
}
then add android:name=".MyApplicationClass" to manifest file
Now you can access the methods in class by
MyApplicationClass applicationClass = (MyApplicationClass)getApplicationContext();
int id = applicationClass .getterMethod().getID;
String playListName = applicationClass .getterMethod().getPlayListName();
and vice versa for Setter();
after that you can use it for data getting and setting Data throughout the application.
Hope it helps :)
References:
https://guides.codepath.com/android/Understanding-the-Android-Application-Class
I find the best to use callbacks.
in ClassA:
Create interface
MyCallback callback;
viod setCallback(MyCallback callback){
this.callback = callback;
}
viod onStop(){
callback = null;
}
interface MyCallback{
void doSomething(Params params);
}
in ClassB:
implement MyCallback
public class ClassB **implements ClassA.MyCallback**
set reference in onCreate
ClassA classA = new ClassA();
classA.setCallback(this);
// override method doSomething
#override
void doSomething(Params params){
//do your thing with the params…
}
when the job is done inside class A call:
callback.doSomething(params);
destroy reference inside class B in onStop()
classA.onStop();
How can I use findViewById() in a non activity class. Below is my code snippet. I get the error message: "can't resolve method findViewById" if used directly. And if i try to use the class constructor (Where the imageView is available) i get this error "cannot resolve symbol context"
public class MyBroadcastReceiver extends FirstBroadcastReceiver {
Activity activity;
public MyBroadcastReceiver(Context context, Activity activity){
this.context=context; // error here(cannot resolve symbol context)
this.activity=activity;
}
#Override
protected void (Context context) {
// content
}
#Override
public void onButton(Context context, boolean isClick) {
if(isClick) {
ImageView blueImage = (ImageView)activity.findViewById(R.id.imageView);
blueImage.setColorFilter(0xff000000);
}
}
.......
....
// and so on
And below is my MainActivity with MybroadcastReceiver class instance.Is it correct?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// and so on
}
}
MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver(MainActivity.this,this);
#Override
public void onActivityResult() {
// some code
}
#Override
public void onInitialized(MyManager manager){
// some code
}
A BroacastReceiver runs entirely in the background, listening for Intents sent either by the OS or other apps. It is not responsible for any UI interactions, and cannot access any views. Therefore, findViewById cannot be used within a BroadcastReceiver.
See also - What is BroadcastReceiver and when we use it?
You have to pass View to the non activity class, before using findViewByid
and
try using
view.findViewByid(R.id.view_id);
Because context is null in Broadcast class. use Broadcast class constructor to pass parent_activity(Where the imageView is available) context in Broadcast to access the context:
public class Broadcast extends BroadCastReceiver {
Activity activity;
public Broadcast(Context context,Activity activity){
this.context=context;
this.activity=activity;
}
.......
....... //so on
and in parent_activity create Broadcast class instance by passing parent_activity context as:
Broadcast broadcast = new Broadcast(parent_activity.this,this);
Use activity instance as:
#Override
public void onButton(Context context, boolean isClick) {
if(isClick) {
ImageView blueImage = (ImageView) activity.findViewById(R.id.imageView); //<--- here
}
}
.........
......... //so on
public class MainActivity extends AppCompatActivity {
public ShareData SD = new ShareData();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SD.set_numb(5);
}
// when button clicked
public void noviEkran(View view){
Intent i = new Intent(this,klasaB.class);
startActivity(i);
}
}
public class ShareData {
private int number;
public ShareData(){
this.number=0;
}
public void set_numb(int num){
number = num;
}
public int get_numb(){
return number;
}
}
public class klasaB extends Activity{
ShareData sd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int i =sd.get_numb();
System.out.println("Saved numb:" + i);
}
}
My question is, if i declare object in 1st class, and set its parameter number to 5, how to acces this number from other class because now my apk crashes when reading " int i =sd.get_numb(); " in class "klasaB".
Any suggestion how to make this work?
ps: i dont want to use static variables, or putExtra with Intents.
If data is simple/primitive then use Intent to pass data from one activity to another. That is what Intent is for.
If it is not (some sort of complex data structure or object), I would extend Application, by making a custom sub class. Application class (as the name implies) is accessible to all Activities, even when app transitions from one to another. Below is a very simple example, just to show you the idea. You can modify/adjust that to your needs.
public class MyApplication extends Application {
private X x;
public static void setX(X x) { ... }
public static X getX() { ... }
}
public class ActivityA extends Activity {
...
MyApplication.setX(x);
}
public class ActivityB extends Activity {
...
X x = MyApplication.getX();
}
You may have mixed up Activity/MainActivity/AppCombatActivity inheritance... I suspect that the reason you are seeing the error -- by the way, please look into "how to ask" and include a bit more information next time -- is that sd in klasaB is never initialized.
MainActivity.SD will hold that 5 after its onCreate(), whereas klasaB.sd is never set to anything.
You never reference or instantiate SD in class B. To get the data to ClassB you will need to set the data as an extra in the intent. Most classes cannot be sent in the intent, so for your case you should pass the primitive types of the object, then create the object.
// when button clicked
public void noviEkran(View view){
Intent i = new Intent(this,klasaB.class);
i.putExtra("TAG", SD.get_num());
startActivity(i);
And then in Class B
ShareData SD = new ShareData();
SD.set_num(getIntent.getIntExtra("TAG", 0);
You can access your class object either using implements Serializable or Parcelable
1.Implement serializable into your ShareData class
public class ShareData implements Serializable{
private int number;
public ShareData(){
this.number=0;
}
public void set_numb(int num){
number = num;
}
public int get_numb(){
return number;
}
}
2.create object of SharedData and share with intent to classB
public class MainActivity extends AppCompatActivity {
public ShareData SD = new ShareData();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SD.set_numb(5);
}
// when button clicked
public void noviEkran(View view){
Intent i = new Intent(this,klasaB.class);
i.putExtras("key", SD)
startActivity(i);
}
}
3.Access in classB
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ShareData sd = (ShareData)getIntent().getSerializableExtra("key").
System.out.println("Saved numb:" + sd.get_num());
}
Use a singleton class
Declare an instance in ShareData class:
public class ShareData {
private static ShareData sdInstance = null;
...}
add this method in ShareData class:
public static ShareData getInstance(){
if(sdInstance == null){
sdInstance = new ShareData();
}
return sdInstance;
}
To get same object in other classes , use this
ShareData sd = ShareData.getInstance();
now you will receive same sd.get_numb()
i'm not asking diffrence, but how to use these referenes?, Class level object to store their reference or use getter everytime which is provided by super class, Which is a better code practice: 1. call getActivity(), getApplicationContext() ..etc everytime in a local method or pass method as parameter when required in an activity or fragment.
Store their reference in a class level object and use it whereever it's required with null check in an activity or fragment.
I would like to know what is more efficient and why?
type1:
Class A extends Activity
{
#Override
public void onCreate()
{
methodA(getApplicationContext());
//or if fragment
methodA(getActivity());
Toast.makeText(getApplicationContext(),...).show();
}
private void methodA(Context mContext)
{
......
......
}
private void methodA()
{
Activity activity = getActivity();
......
......
}
}
type2:
class A extends Activity{
private Activity mContext;
private Activity mActRef; //if fragment
#Override
public void onCreate()
{
mContext = getApplicationContext();
mActRef = getActivity();//if fragment;
methodA(mContext);
//or if fragment
methodA(mActRef);
..........
.........
.........
Toast.makeText(mContext,...).show();
}
private void methodA(Context mContext)
{
......
......
}
private void methodA()
{
Toast.makeText(mContext,....).show();
}
}
}
getActivity() and getApplicationContext() both return the context and available throughout the class extend with Activity.
According to my opinion No need to create a global variable for them because they are available at class level. Both are correct but storing the context is not efficient.
I have the following code in which I am using the application context to retrieve needed information:
public class Data{
private boolean VarA;
public void setVarA(boolean B,Context ctx)
{
SharedPreferences CoreDataStorage = ctx.getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = CoreDataStorage.edit();
editor.putBoolean("PrefVarA", VarA);
edit.commit();
}
}
Now I am calling the public method setVarA() from the below class
public class MyActivity extends Activity{
Data cd = new Data();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.registration);
cd.setVarA(true,this);
}
}
In the activity above it shows me compilation error that it can't cast from MyActivity to Context. Please suggest any solution. Is the above code is not proper way to pass the context?
You need the application Context to access the shared preferences. It should be:
cd.setVarA(true,this.getApplicationContext());
in the onCreate of MyActivity.