2021. január 3., vasárnap

Android fejlesztés 8 : Adatbázis használata

 Adatbázis használata android rendszerben








activity_db.xlm layout létrehozása a megjelenítés kialakításához:

<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
xmlns:tools = "http://schemas.android.com/tools"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".MainActivity"
android:orientation = "vertical">
<EditText
android:id = "@+id/name"
android:layout_width = "match_parent"
android:hint = "Enter Name"
android:layout_height = "wrap_content" />
<EditText
android:id = "@+id/salary"
android:layout_width = "match_parent"
android:inputType = "numberDecimal"
android:hint = "Enter Salary"
android:layout_height = "wrap_content" />

<LinearLayout
android:layout_width = "wrap_content"
android:layout_height = "wrap_content">
<Button
android:id = "@+id/save"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:drawableLeft="@android:drawable/ic_menu_add"/>
<!-- android:text = "SAV" android:textSize="24sp" -->
<Button
android:id = "@+id/refresh"
android:drawableLeft="@android:drawable/ic_menu_info_details"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" />
<Button
android:id = "@+id/filter"
android:drawableLeft="@android:drawable/ic_menu_search"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" />
<Button
android:id = "@+id/update"
android:drawableLeft="@android:drawable/ic_menu_edit"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" />
<Button
android:id = "@+id/delete"
android:drawableLeft="@android:drawable/ic_menu_delete"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" />
</LinearLayout>
<ListView
android:id = "@+id/listView"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="5dp"
android:layout_gravity="start"
android:textDirection="ltr"
android:fastScrollAlwaysVisible="true"
android:listSelector="@color/teal_200"
>
</ListView>
<!-- rtl:jobbra | ltr ballra igazítás -->
</LinearLayout>





Az adatbázis kapcsolatvezérlő létrehozása:

package hu.mierdekel.mietest01;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import java.io.IOException;
import java.util.ArrayList;

public class MieDatabaseHelper extends SQLiteOpenHelper {

public static final String DATABASE_NAME = "MieDatabase";
public static final String MIE_TABLE_NAME = "MieTableSalary";
private String mieTableName;

public MieDatabaseHelper(Context context) {
super(context,DATABASE_NAME,null,1);
}

@Override
public void onCreate(SQLiteDatabase db) {
try {
//--- Tábla létrehozása
db.execSQL(
"create table "+ MIE_TABLE_NAME +"(id INTEGER PRIMARY KEY, name text,salary text )"
);
db.close();
} catch (SQLiteException e) {
try {
throw new IOException(e);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//--- Induló tábla létrehozása
db.execSQL("DROP TABLE IF EXISTS "+ MIE_TABLE_NAME);
onCreate(db);
}

//--- DB beszúrás
public boolean insert(String s, String s1) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("name", s);
contentValues.put("salary", s1);
db.insert(MIE_TABLE_NAME, null, contentValues);
db.close();
return true;
}
//--- DB olvasás (összes, szürt)
public ArrayList getAllCotacts(String param) {
SQLiteDatabase db = this.getReadableDatabase();
ArrayList<String> array_list = new ArrayList<String>();
Cursor res = db.rawQuery( "select * from "+ MIE_TABLE_NAME +" WHERE name like '"+param+"' ", null );
res.moveToFirst();
while(res.isAfterLast() == false) {
array_list.add(res.getString(1) + " | " +res.getString(2));
res.moveToNext();
}
res.close();
db.close();
return array_list;
}

//--- DB törlés
public int delete(String param) {
int count = 1;
try {
SQLiteDatabase db = this.getWritableDatabase();

// db.delete(MIE_TABLE_NAME, " name like '?%' ", new String[]{String.valueOf(param)}); // SQLite-n nem működik !!!
db.execSQL( "delete from " + MIE_TABLE_NAME + " where name like '" + param + "' " );
db.close();
} catch (SQLiteException e) {
try {
throw new IOException(e);
} catch (IOException e1) {
e1.printStackTrace();
}
}
return count;
}

//--- DB módósítás
public int update(String name_p, String value_p) {
int count = 1;
ContentValues values = new ContentValues();
values.put("name", name_p);
values.put("salary", value_p);
try {
SQLiteDatabase db = this.getWritableDatabase();
db.update(MIE_TABLE_NAME, values, " name like '" + name_p + "' ", null);
db.close();
} catch (SQLiteException e) {
try {
throw new IOException(e);
} catch (IOException e1) {
e1.printStackTrace();
}
}
return count;
}

}


Adatbázis művelet vezérlő activity létre hozása:

package hu.mierdekel.mietest01;

import android.app.Activity;
import android.os.Bundle;
//import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Map;

public class DbActivity extends Activity { // AppCompatActivity
Button save, refresh;
EditText name, salary;
private ListView listView;

@Override
protected void onCreate(Bundle readdInstanceState) {
super.onCreate(readdInstanceState);
setContentView(R.layout.activity_db);

final MieDatabaseHelper helper = new MieDatabaseHelper(this);
final ArrayList array_list = helper.getAllCotacts("%");

name = findViewById(R.id.name);
salary = findViewById(R.id.salary);

listView = findViewById(R.id.listView);
final ArrayAdapter arrayAdapter = new ArrayAdapter(DbActivity.this, android.R.layout.simple_list_item_1, array_list); //simple_list_item_1,
/*
ArrayList<Map<String, String>> list = array_list ;
String[] from = { "name", "salary" };
int[] to = { R.id.name, R.id.salary };
final SimpleAdapter arrayAdapter = new SimpleAdapter(DbActivity.this, array_list,
android.R.layout.simple_list_item_2,
from,
to); //simple_list_item_1,
// SimpleAdapter adapter = new SimpleAdapter(this, list, android.R.layout.simple_list_item_2, from, to);
*/
listView.setAdapter(arrayAdapter);

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, final View view,
int position, long id) {
final String item = (String) parent.getItemAtPosition(position);
view.animate().setDuration(2000).alpha(0)
.withEndAction(new Runnable() {
@Override
public void run() {
name = findViewById(R.id.name);
name.setText(item);
array_list.remove(item); //-- eltüntetés
arrayAdapter.notifyDataSetChanged();
listView.invalidateViews();
listView.refreshDrawableState();
}
});
}

});



//--- DB Olvasás
findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
array_list.clear();
array_list.addAll(helper.getAllCotacts("%"));
arrayAdapter.notifyDataSetChanged();
listView.invalidateViews();
listView.refreshDrawableState();
}
});

//--- DB Írás
findViewById(R.id.save).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!name.getText().toString().isEmpty() && !salary.getText().toString().isEmpty()) {
if (helper.insert(name.getText().toString(), salary.getText().toString())) {

//--- Adatok beírás utánni ujra olvasása
array_list.clear();
array_list.addAll(helper.getAllCotacts("%"));
arrayAdapter.notifyDataSetChanged();
listView.invalidateViews();
listView.refreshDrawableState();

Toast.makeText(DbActivity.this, "Inserted", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(DbActivity.this, "NOT Inserted", Toast.LENGTH_LONG).show();
}
} else {
name.setError("Enter NAME");
salary.setError("Enter Salary");
}
}
});

//--- DB szűrés
findViewById(R.id.filter).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
name = findViewById(R.id.name);
array_list.clear();
array_list.addAll(helper.getAllCotacts(name.getText().toString()));
arrayAdapter.notifyDataSetChanged();

listView.invalidateViews();
listView.refreshDrawableState();
}
});


//--- DB törlés
findViewById(R.id.delete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

if (!name.getText().toString().isEmpty()) {
int deleted = 1;
deleted = helper.delete(name.getText().toString());
if (deleted > 0) {
//--- Adatok törlés utánni ujra olvasása
array_list.clear();
array_list.addAll(helper.getAllCotacts("%"));
arrayAdapter.notifyDataSetChanged();
listView.invalidateViews();
listView.refreshDrawableState();

Toast.makeText(DbActivity.this, "Deleted name filter : " + name.getText().toString(), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(DbActivity.this, "NOT Deleted", Toast.LENGTH_LONG).show();
}

} else {
name.setError("Delete : Enter NAME");
}

}
});



//--- DB módosítás
findViewById(R.id.update).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!name.getText().toString().isEmpty() && !salary.getText().toString().isEmpty()) {
if (helper.update(name.getText().toString(), salary.getText().toString()) > 0) {

//--- Adatok módosítás utánni ujra olvasása
array_list.clear();
array_list.addAll(helper.getAllCotacts("%"));
arrayAdapter.notifyDataSetChanged();
listView.invalidateViews();
listView.refreshDrawableState();

Toast.makeText(DbActivity.this, "Updated", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(DbActivity.this, "NOT Updated", Toast.LENGTH_LONG).show();
}
} else {
name.setError("Enter NAME");
salary.setError("Enter Salary");
}
}
});


}
}


Fő aktivity menőpontról indíthatóság kialakítás:

public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (item.getItemId()) {
case R.id.action_settings3:
Intent prefIntent3 = new Intent(MainActivity.this, MiePrefActivity.class);
startActivity(prefIntent3);
break;

case R.id.action_settings2:
Intent prefIntent2 = new Intent(MainActivity.this, MiePrefActivity2.class);
startActivity(prefIntent2);
break;

case R.id.action_exit:
finish();
break;


case R.id.action_db:
Intent prefIntentdb = new Intent(MainActivity.this, DbActivity.class);
startActivity(prefIntentdb);
break;


Manifest filebe elhelyezése az új aktivity -nek


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="hu.mierdekel.mietest01">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MieTest01">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.MieTest01.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MiePrefActivity2"
android:label="@string/app_name"
android:theme="@style/Theme.MieTest01.NoActionBar">
</activity>
<activity
android:name="MiePrefActivity"
android:label="@string/app_name"
android:theme="@style/Theme.MieTest01.NoActionBar">
</activity>
<activity
android:name="DbActivity"
android:label="@string/app_name"
android:theme="@style/Theme.MieTest01.NoActionBar">
</activity>



</application>

</manifest>




AndroidStudioban az assets konyvtár létrehozása és használata




Használata:

public class InfoHtmlActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_info_html);
WebView webView = findViewById(R.id.miewebview);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
// webView.loadUrl("file:///android_asset/ic.png");
webView.loadUrl("file:///android_asset/index.html"); /// a konyvtár assets de a hívatkozás asset (S nélkül)
// webView.loadUrl("https://mierdekel.hu");
/*
String data = "<!DOCTYPE html>";
data += "<head><title>Hello World</title></head>";
data += "<body>Welcome to the WebView</body>";
data += "</html>";
// args: data, mimeType, encoding
webView.loadData(data, "text/html", "UTF-8");

}




Link a program teszteléséről:

https://youtu.be/2ozXtTVCxN0





Android fejlesztés 7 : Stílus és téma használata


Mi a cél?


Megjelenítés és vizuális hatás (élmény) személyre szabhatósága közelebb hozza a felhasználót az alkalmazáshoz.

Az alkalmazás megjelenítése olyan mint a divat, változhat és a megjelenítési változást meg kell engedni.



                      







Mi a módszer?

Az erőforrásoknál az xml filekben a megjelenítésre is megadhatunk paramétereket, sőt ezeket akár futás időben is megváltoztathatjuk.


Manuális definíciók:


Stílusok  apps/res/value/style.xml file:
<resources>
     <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
       <item name="colorPrimary">@color/colorPrimary</item>
       <item name="colorPrimayDark">@color/colorPrimaryDark</item>
       <item name="colorAccent">@color/colorAccent</item>
       <item name="android:windowBackground">@color/colorAccent</item>
   </style>
   <style name="TextviewStyle" parent="@android:style/Widget.TextView">
       <item name="android:layout_width">wrap_content</item>
       <item name="android:layout_height">wrap_content</item>
       <item name="android:layout_marginLeft">0dp</item>
       <item name="android:layout_marginTop">10dp</item>
       <item name="android:textColor">#86AD33</item>
       <item name="android:textStyle">bold</item>
       <item name="android:textSize">20dp</item>
   </style>
   <style name="ButtonStyle" parent="@android:style/Widget.Button">
       <item name="android:layout_width">wrap_content</item>
       <item name="android:layout_height">wrap_content</item>
       <item name="android:layout_marginLeft">20dp</item>
       <item name="android:layout_marginTop">10dp</item>
       <item name="android:textColor">@color/colorIt</item>
       <item name="android:textStyle">bold</item>
       <item name="android:textSize">30dp</item>
   </style>

   <string name="wlcmsg">Welcome to DataFlair</string>
</resources>


 Színek app>res>value>color.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <color name="colorPrimary">#00cccc</color>
   <color name="colorPrimaryDark">#006666</color>
   <color name="colorIt">#188596</color>
   <color name="colorAccent">#BBF1F1</color>
   <color name="colorAccent1">#1397B1</color>
</resources>

Használat style zöld, egyedi beállítások kék színnel
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_marginLeft="10dp"
   android:orientation="vertical">

   <TextView
       android:id="@+id/TextView1"
       android:layout_width="300dp"
       android:layout_height="50dp"
       android:layout_marginLeft="45dp"
       android:layout_marginTop="100dp"               
       android:fontFamily="@font/abhaya_libre_extrabold"
       android:text="@string/wlcmsg"
       android:textColor="@color/colorAccent1"
       android:textSize="25dp" />

   <TextView
       android:id="@+id/btnShow"
       style="@style/ButtonStyle"
       android:layout_marginLeft="35dp"
       android:layout_marginTop="200dp"
       android:fontFamily="@font/abhaya_libre_extrabold"
       android:gravity="center"
       android:text="Android Style of a View" />
</LinearLayout>





Mi az eszköz?

Alapbeállítási készlet létrehozása cél alkalmazások vannak mert XML szerkesztések körülményesek.





Kilépés a programból

:

moveTaskToBack(true);

android.os.Process.killProcess(android.os.Process.myPid());

System.exit(1);




Rövidítések

SDK -> Software Development Kit -> Fejlesztő készlet 

AVM -> Android Virtual Machine  -> Android Virtuális Gép

ADB -> Android Debug Bridge     -> Hibakeresési futtatásért felelős modul

ADM -> Android Device Monitor   -> fileszintű böngészése az emulátornak

NDK -> Native Development Kit   -> C++ nyelvű programozáshoz



Javaslatok

 

Minimális támogatott verzió 4.4-es Android




Használjunk lehetőleg :  AppCompatActivity -t




Formázzunk újra a kódunkat

  • Mindent kijelöl : Control+A  vagy menűből Android Studio Edit > Select All.
  • Újra formáz :     Studio menu Code > Reformat Codevagy Ctrl+Alt+L 

 

Hiba kezelés:


"AAPT2 error" -> gradle.properties -> android.enableAapt2=false

 





Hol mélyedhetünk el még jobban a témában?


Linkek android stílus és témában

https://developer.android.com/jetpack/compose

https://developer.android.com/guide/navigation

https://developer.android.com/design/index.html


https://developer.android.com/studio/index.html                       

https://developer.android.com/training/index.html                                              /// Oktatás

https://developer.android.com/guide/index.html                                                 /// Programozás alapok

https://developer.android.com/reference/android/package-summary.html            /// API és csomagok  

https://developer.android.com/guide/components/activities/activity-lifecycle.html  //életciklus

https://developer.android.com/reference/android/Manifest.permission.html          /// alkalmazás engedélyek

https://developer.android.com/reference/java/lang/System.html                          /// rendszer process info

https://developer.android.com/reference/android/os/Process.html                      /// rendszer process info

https://developer.android.com/reference/java/io/File.html                                   /// files

 

https://developer.android.com/reference/android/graphics/Canvas.html  /// rajzolás

https://developer.android.com/reference/android/graphics/Paint.html


https://material.io/design/color/the-color-system.html#tools-for-picking-colors


https://developer.android.com/courses/android-basics-kotlin/course

https://github.com/google-developer-training/android-basics-kotlin-birthday-card-app-solution

https://google.dev/u/me?utm_source=developer.android.com

https://material.io/design/color/the-color-system.html#tools-for-picking-colors



https://codelabs.developers.google.com/

https://google.dev/u/113404918216233556667?utm_source=developer.android.com

https://developers.google.com/learn/pathways

https://developers.google.com/learn


 Oktatás:

https://www.tutorialspoint.com/android/android_alert_dialoges.htm

https://stuff.mit.edu/afs/sipb/project/android/docs/guide/topics/ui/notifiers/toasts.html

https://www.tutlane.com/tutorial/android/android-styles-and-themes-with-examples



Online szerkesztők:

https://material.io/design/environment/surfaces.html#properties

https://glitch.com/~material-theme-builder



Google play közzététel:

https://play.google.com/apps/publish/?hl=hu   ///publikálás




2021. január 2., szombat

Android fejlesztés 6 : Beállítások felület készítése

 Fő aktívity menüjéből kiválasztható alapbeállítások elkészítése

























Manifest filebe felvesszük a preferencia beállító aktivityket





A fő aktivitybe menüben kiválaszthatóvá tesszük a beállítás aktivity-ket (java és kotlin nyelvűt is készítettem)



Java:




Kotlin:



Elkészítjük az erőforrásokat (layout, menu, values, xml, ...)




Beállítások, 'gyógyítások':

A gradle.properties file-ben fel vettem az alábbi két sort

  • android.useAndroidX=true
  • android.enableJetifier=true

Az androidx-es beállításokat használtam

  •   android.support.constraint.ConstraintLayout
  •   androidx.constraintlayout.widget.ConstraintLayout


Automatikus erőforrás használat deffinicót állítottam:

  • xmlns:app="http://schemas.android.com/apk/res-auto"


Licenceket újra engedélyeztem:

  •  c:\Users\xxxx\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat --licenses


Build.gradle(module app) -ban az alábbi bővítéseket tettem:

  • implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
  • implementation 'androidx.appcompat:appcompat:1.1.0'
  • implementation 'com.android.support:design:28.0.0'



Párszor kiürítettem a cache-t

  • Android Studio -> File -> Invalidate cache/restart