original source :  https://medium.com/@amit.bhandari/storing-java-objects-other-than-primitive-types-in-room-database-11e45f4f6d22

compile "android.arch.persistence.room:runtime:1.0.0-alpha3"annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha3"compile 'com.google.code.gson:gson:2.6.2'

First 2 lines for including Room DB in our project and 3rd one is Gson which we will use to convert our object to String.

Our modified User.java looks something like this. Even though you can’t see any getter or setter method here, you need to include them or make the fields public for Room to access it.

User.java

@Entitypublic class User {   @PrimaryKey   private int uId;   private String uName;   private ArrayList<String> uPets = new ArrayList<>();   public User() {   }   public User(int id, String name, List<String> pets){      this.uId = id;      this.uName = name;      this.uPets.addAll(pets);   };   //getters setters removed for brevity}

User DAO stays more or less the same. You can include methods to fetch particular user from user id or name, I will leave that as an exercise for you.

UserDAO.java

@Daopublic interface UserDAO {   @Insert(onConflict = REPLACE)   void insertUser(User user);   @Query("SELECT * FROM User")   List<User> getUsers();   //include any methods to fetch specific user   // @Query("SELECT * FROM User")}

And our UserDB will also stay the same except small difference.

UserDB.java

@Database (entities = {User.class},version = 1)@TypeConverters({Converters.class})
public abstract class UserDB extends RoomDatabase {   public abstract UserDAO userDAO();}

Noticed that @TypeConverters annotation we provided along with @Database annotation, this will be the class which will tell Room how to convert ArrayList object to one of SQLite data type. We will implement methods to convert ArrayList to String for storing it in DB and String back to ArrayList for getting back original User object.

Type Converter specifies additional type converters that Room can use. The TypeConverter is added to the scope of the element so if you put it on a class / interface, all methods / fields in that class will be able to use the converters.

Without further delay, we will see how our type converter looks in our case.

UserDAO.java

public class Converters {   @TypeConverter   public static ArrayList<String> fromString(String value) {      Type listType = new TypeToken<ArrayList<String>>() {}.getType();      return new Gson().fromJson(value, listType);   }   @TypeConverter   public static String fromArrayLisr(ArrayList<String> list) {      Gson gson = new Gson();      String json = gson.toJson(list);      return json;   }}

As you can see, we have 2 methods in TypeConverter.

  1. public static String fromArrayLisr(ArrayList<String> list) : This method takes our arraylist object as parameter and returns string representation for it so that it can be stored in Room Database. Very simple and easy way to convert any object to string is converting it into its JSON equivalent. Just creating Gson object and calling toJson method with our object as parameter is enough.
  2. public static ArrayList<String> fromString(String value) : While reading data back from Room Database, we get JSON form of our arraylist which we need to convert back. We will use Gson method fromJson by providing JSON string as parameter. But while converting back, we also need to provide the class of original object (in our case, arraylist), but providing arraylist is not enough here as Gson will not be able know what kind of list it has to form. That’s why we used Type to provide the type of list we want Gson to form for us from the JSON string.

.

.

.

.

참고사항) @Bindable 에 대하여

https://medium.com/@jencisov/androids-data-binding-s-baseobservable-class-and-bindable-annotation-in-kotlin-1a5c6682a3c1

https://www.youtube.com/playlist?list=PLJJzW__bab3SF33vwvlA_F7PPN6NxkHdQ

image
image
image
image
image
image
image
image
image

.

.

.

.

room dependencies추가 

image
image
image

.

.

.

.

entity class

image
image

.

.

.

.

DAO 만들기

image

.

.

.

.

database 만들기

image

.

.

.

.

실제 사용 예시

image
image

allowMainThreadQueries()를 통해 메인쓰레드에서도 query가 작동가능하게 된다.

본래는 다른 thread에서 해줘야 한다.

image

.

.

.

.

room database callback 

onCreate() 데이터베이스가 생성될때 호출된다.

onOpen()은 데이터베이스가 열릴때 호출된다

image
image
image

.

.

.

.

.

.

Room with coroutines

10분분량 개념잡기 좋다.

https://youtu.be/CcaCpRCACzU

.

.

.

.

.

한국사는 외국인 개발자 설명 Room with coroutines

https://youtu.be/Rm_B32ZB7s4

image

아래는 coroutines사용을 위해 suspend를 추가한 모습

image

이 개발자는 기본 Fragment를 extend해서 coroutine의 기능을 추가하고 이를 모든 fragment에 사용하려고 한다.

image
image

아래는 Context를 extension func 추가 해서 toast를 쉽게 하는 팁설명

image
image

.

.

.

.

.

jetpack room with coroutines in kotlin

https://youtu.be/kF0TPehhIx0

image
image
image
image
image
image

.

.

.

.

참고사항)

room sqlite에 primitive 타입이 아닌 다른 데이터를 저장해야 하는 경우 (obj를 json string으로 변경해서 sqlite database에 저장한다.)

https://medium.com/@amit.bhandari/storing-java-objects-other-than-primitive-types-in-room-database-11e45f4f6d22

https://youtu.be/W0ag98EDhGc

androidTest는 android component관련 테스트할때 사용한다.

일반 java, kotiln 테스트는 test를 이용한다.

.

.

필요한 dependencies

.

.

원본 소스 코드 (테스트될 코드)

.

.

오른쪽 클릭

.

.

JUnit4가 안드로이드와 더 잘 작동 (2020 기준)

.

.

.

.

테스트 코드

Android Framework Components

https://www.youtube.com/playlist?list=PLIUuxxIJtMjWR77V4_QbKZY0gZb1kzoJ8

android가 어떻게 구성되어 있는지 좀더 깊이 설명하는 강좌

android official docs : https://developer.android.com/guide/topics/connectivity/usb/host

In general, you obtain a UsbManager to retrieve the desired UsbDevice. When you have the device, you need to find the appropriate UsbInterface and the UsbEndpoint of that interface to communicate on. Once you obtain the correct endpoint, open a UsbDeviceConnection to communicate with the USB device.

usb지원은 API Level 12 or higher

android manifest

  • Because not all Android-powered devices are guaranteed to support the USB host APIs, include a <uses-feature> element that declares that your application uses the android.hardware.usb.host feature.(이것은 기본적으로 항상 넣어야 하는 내용이다)
  • 이미 연결되어 있는 usb기기를 사용하는 경우(wasent 개발에 사용했음) If you want your application to be notified of an attached USB device, specify an    <intent-filter>     and    <meta-data>    element pair for the android.hardware.usb.action.USB_DEVICE_ATTACHED    intent in your main activity. The    <meta-data>    element points to an external XML resource file that declares identifying information about the device that you want to detect.In the XML resource file, declare    <usb-device>    elements for the USB devices that you want to filter. The following list describes the attributes of    <usb-device>. In general, use vendor and product ID if you want to filter for a specific device and use class, subclass, and protocol if you want to filter for a group of USB devices, such as mass storage devices or digital cameras. You can specify none or all of these attributes. Specifying no attributes matches every USB device, so only do this if your application requires it:vendor-idproduct-idclasssubclassprotocol (device or interface)Save the resource file in the res/xml/ directory. The resource file name (without the .xml extension) must be the same as the one you specified in the <meta-data> element. The format for the XML resource file is in the example below.

AndroidManifest.xml의 예시

<manifest ...>
   <uses-feature android:name="android.hardware.usb.host" />
   <uses-sdk android:minSdkVersion="12" />
   ...
   <application>
       <activity ...>
           ...
           <intent-filter>
               <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
           </intent-filter>

           <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
               android:resource="@xml/device_filter" />
       </activity>
   </application>
</manifest>

res/xml/device_filter.xml 의 예시

<?xml version="1.0" encoding="utf-8"?>

<resources>
   <usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>

.

.

.

android에서 usb를 사용하는 과정을 아래와 같다.

  1. Discover connected USB devices by using an intent filter to be notified when the user connects a USB device or by enumerating USB devices that are already connected.
  2. Ask the user for permission to connect to the USB device, if not already obtained.
  3. Communicate with the USB device by reading and writing data on the appropriate interface endpoints.

1번과정 discover하는 방법은 두가지가 있다.

– Use an intent filter

– Enumerate devices

.

.

Use an intent filter를 이용 discover

<activity ...>
...
   <intent-filter>
       <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
   </intent-filter>

   <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
       android:resource="@xml/device_filter" />
</activity>
<?xml version="1.0" encoding="utf-8"?>

<resources>
   <usb-device vendor-id="1234" product-id="5678" />
</resources>
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)

.

.

Enumerate devices를 이용 discover 

val manager = getSystemService(Context.USB_SERVICE) as UsbManager

val deviceList = manager.getDeviceList()
val device = deviceList.get(“deviceName”)

val manager = getSystemService(Context.USB_SERVICE) as UsbManager
..
val deviceList: HashMap<String, UsbDevice> = manager.deviceList
deviceList.values.forEach { device ->
   //your code
}

.

.

.

.

obtaining permission

Note: If your application uses an intent filter(위에서 첫번째방법을 사용하는 경우) to discover USB devices as they’re connected, it automatically receives permission if the user allows your application to handle the intent. If not, you must request permission explicitly in your application before connecting to the device.

https://stackoverflow.com/questions/14111353/android-bluetooth-printing/53922171#53922171

https://developer.android.com/training/printing

https://stackoverflow.com/questions/43462836/android-print-to-any-bluetooth-printer

https://www.androidcode.ninja/android-bluetooth-tutorial/

https://stackoverflow.com/questions/14796422/how-to-send-data-to-bluetooth-printer-via-android-app