강의 링크 : https://www.youtube.com/watch?v=PKnWgQsbwuw&t=465s
1. Files and Storage
- 안드로이드는 두 장소에서 파일을 읽어올 수 있다 : 내부/외부 저장소. 둘 다 persistent storage이며, 전원을 꺼도 데이터는 유지된다
- internal storage : Built into device
* guaranteed to be present
* typically smaller
* can't be expanded to removed
* specific and private to each app
* wiped out when the app is uninstalled
- 내부 저장수에 파일을 넣고 싶으면? res/raw폴더
2. File and Streams
- java.io.File : 파일이나 디렉토리를 나타내는 객체 Objects that represent a file or directory
* 메소드들 : canRead, canWrite, create, delete, exits, getName, getParent, getPath, isFile, isDirectory, lastModified, length, listFiles, mkdir, mkdirs, renameTo
- java.io.InputStream, OutputStream : 특정 소스에서 데이터가 들어오고 나가는 흐름을 나타내는 객체Stream objects represent flows of data bytes from/to a source of destination.
* Could come from a file, network, database, memory, ..
* Normally not directly used; they only include low-level methods for reading/writing a byte at a time from the input.
* 바이트단위로 밖에 안되고 try/catch해야되서 불편함
* java.util.Scanner, java.io.BufferedReader, java.io.PrintStream 등 실제 읽기/쓰기를 하는 객체의 매개변수로 많이 사용됨
3. Scanner
4. Using internal storage
- 파일을 읽고 쓸 수 있는 메소드들
getResources().openRawResource(R.raw.id) // read an input from res/raw getFilesDir() // returns internal directory for your app getCacheDir() // returns a "temp" directory for scrap files openFileInput("name", mode) // opens a file for reading
openFileOutput("name", mode) // opens a file for writing |
-많은 메소드들이 표준 java.io.File 객체를 반환/ 몇몇은 java.io.InputStream 또는 OutputStream 객체를 반환해서 Scanner, BufferReader, PrintStream 과 함께 쓸 수 있음
5. 단어장 프로젝트 파일에서 읽기
package com.example.han.lec3ninjaturtles;
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.ListView; import android.widget.TextView; import android.widget.Toast;
import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Scanner;
public class MainActivity extends AppCompatActivity { private HashMap<String, String> dictionary; private ArrayList<String> list; private ArrayAdapter<String> adapter; private ArrayList<String> fiveDefinition;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
dictionary = new HashMap<String, String>();
fiveDefinition = new ArrayList<String>();
readWordsFromFile(); pickRandomWord();
} private void readWordsFromFile(){ // read file => into list
list = new ArrayList<String>();
//res/raw에 hello.txt가 있다고 가정 Scanner sc = new Scanner(getResources().openRawResource(R.raw.words));
// sc.useDelimiter(" - "); // 이렇게 읽으면 hasNext(); 로 읽어들이면 됨 while(sc.hasNextLine()){ String line = sc.nextLine(); String wordAndDef[] = line.split(" - "); list.add(wordAndDef[0]); dictionary.put(wordAndDef[0], wordAndDef[1]); } sc.close(); } private void pickRandomWord(){ ArrayList<String> fiveWords = new ArrayList<String>(); //shuffle word Collections.shuffle(list); for(int i = 0 ; i < 5; i++){ fiveWords.add(list.get(i)); } // 하나 골라서 문제냄 final String theWord = fiveWords.get(0); // list of matched definition
fiveDefinition.clear(); for(String word: fiveWords) fiveDefinition.add(dictionary.get(word)); Collections.shuffle(fiveDefinition);
//listView를 위한 adapter를 만들어야 함 if(adapter==null){ adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, fiveDefinition); }else{ adapter.notifyDataSetChanged(); } ListView listView = (ListView)findViewById(R.id.word_list); listView.setAdapter(adapter);
TextView word = (TextView)findViewById(R.id.word); word.setText(theWord);
// clickable하게 만들기 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { // new anonymous 어쩌고를 만들면 위에서 변수 선언할 때 final이어야 함 @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { String defnClicked = fiveDefinition.get(position); String rightAnswer = dictionary.get(theWord); if(defnClicked.equals(rightAnswer)) { /* Toast.makeText(this, "you got it!", Toast.LENGTH_SHORT).show(); * 지금 this는 activity 가 아님 */ Toast.makeText(MainActivity.this, "you got it!", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(MainActivity.this, "wrong!", Toast.LENGTH_SHORT).show(); }
pickRandomWord();
} }); }
} |
6. make new file 34분
단어를 추가/수정하고 싶으면 새로운 파일을 만들어야 함. (처음에 추가한 텍스트파일은 이미 앱에 박힌 상태라서)
7. External storage
- 기기에 따라 나타나지 않을 수도 있음
- 다른 앱이나 유저들이 읽거나 쓸 수도 있음. not private to your app
- 앱을 지워도 삭제 되지 않음. 몇몇 클래스는 예외
- 앱이 기기의 외부 저장소에 읽기/쓰기가 필요하다면 AndroidManifest.xml파일에서 permission을 명시해 줘야 함.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.han.lec3ninjaturtles"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ... </manifest>
|
예시코드
8. Stanford Library
-라이브러리 추가하기
http://web.stanford.edu/class/cs193a/lib/ 에서 stanford-android-lib.jar파일을 다운받은 후 app/libs에 넣음.
탐색기 위에 android를 project로 바꾸면 프로젝트 내 모든 파일을 볼 수 있음. 여기서 .jar파일을 우클릭 후 add as library
public class MainActivity extends SimpleActivity{ // extends Activity 대신에 이렇게 씀
- 몇몇 기능
* casting 없이 find를 할 수 있음
// ListView listView = (ListView)findViewById(R.id.word_list);
ListView listView = (ListView)find(R.id.word_list); |
* textView찾기와 setText를 한 줄에
// TextView word = (TextView)findViewById(R.id.word); // word.setText(theWord);
findTextView(R.id.word).setText(theWord); |
*Log, Print, Toast
*List
// ListView listView = (ListView)findViewById(R.id.word_list); ListView listView = (ListView)find(R.id.word_list); // listView.setAdapter(adapter);
/* //listView를 위한 adapter를 만들어야 함 if(adapter==null){ adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, fiveDefinition); }else{ adapter.notifyDataSetChanged(); }*/ SimpleList.with(this) .setItems(listView, fiveDefinition); |
최종 코드
SimpleList.with().setItems() 부분이 자꾸 에러나서 그냥 어댑터로 돌렸다.
package com.example.han.lec3ninjaturtles;
import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast;
import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Scanner;
import stanford.androidlib.SimpleActivity;
public class MainActivity extends SimpleActivity { private HashMap<String, String> dictionary; private ArrayList<String> list; private ArrayAdapter<String> adapter; private ArrayList<String> fiveDefinition; private String theWord;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
dictionary = new HashMap<String, String>(); fiveDefinition = new ArrayList<String>();
readWordsFromFile(); pickRandomWord();
} private void readWordsFromFile(){ // read file => into list
list = new ArrayList<String>();
//res/raw에 hello.txt가 있다고 가정 Scanner sc = new Scanner(getResources().openRawResource(R.raw.words));
// sc.useDelimiter(" - "); // 이렇게 읽으면 hasNext(); 로 읽어들이면 됨 while(sc.hasNextLine()){ String line = sc.nextLine(); String wordAndDef[] = line.split(" - "); list.add(wordAndDef[0]); dictionary.put(wordAndDef[0], wordAndDef[1]); } sc.close(); } private void pickRandomWord(){ ArrayList<String> fiveWords = new ArrayList<String>();
//shuffle word Collections.shuffle(list); for(int i = 0 ; i < 5; i++){ fiveWords.add(list.get(i)); }
// 하나 골라서 문제냄 theWord = fiveWords.get(0); // TextView word = (TextView)findViewById(R.id.word); // word.setText(theWord); findTextView(R.id.word).setText(theWord);
// list of matched definition fiveDefinition.clear(); for(String word: fiveWords) fiveDefinition.add(dictionary.get(word)); Collections.shuffle(fiveDefinition);
/* // stanford library로 listView 적용하기 // 이 부분에서 자꾸 에러가 남! ListView listView = (ListView)findViewById(R.id.word_list); SimpleList.with(this).setItems(listView, fiveDefinition);*/
//listView를 위한 adapter를 만들어야 함 ListView listView = (ListView)find(R.id.word_list); if(adapter==null){ adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, fiveDefinition); }else{ adapter.notifyDataSetChanged(); } listView.setAdapter(adapter);
// listen to clicks on listview // 리스트를 클릭하면 onItemClick 호출 listView.setOnItemClickListener(this);
// clickable하게 만들기 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { // new anonymous 어쩌고를 만들면 위에서 변수 선언할 때 final이어야 함 @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { String defnClicked = fiveDefinition.get(position); String rightAnswer = dictionary.get(theWord); if(defnClicked.equals(rightAnswer)) { // Toast.makeText(this, "you got it!", Toast.LENGTH_SHORT).show(); // * 지금 this는 activity 가 아님 toast("you got it!"); // Toast.makeText(MainActivity.this, "you got it!", Toast.LENGTH_SHORT).show(); }else { toast("wrong", Toast.LENGTH_LONG); // Toast.makeText(MainActivity.this, "wrong!", Toast.LENGTH_SHORT).show(); }
pickRandomWord();
} });
}
// 리스트 클릭에 스탠포드 라이브러리 이용 @Override public void onItemClick(ListView list, int index) { String defnClicked = fiveDefinition.get(index); String rightAnswer = dictionary.get(theWord); if(defnClicked.equals(rightAnswer)) { toast("you got it!"); }else { toast("wrong", Toast.LENGTH_LONG); } pickRandomWord(); }
} |
9. Styles and Themes
- 색깔 정의 :
<color>태그에 정의(hex strings로 #RRGGBB) 하고 이름을 지정 @color/name
res/values/styles.xml |
<resources> <color name="orangeee">#FF0000</color> ... </resources> |
- res/ : resource files (주로 XML)
* drawable/ :imgaes
* layout/ : descriptions of GUI layout
* menu/ : overall app menu options
* values/ : constant values, arrays, styles (ex, styles.xml)
* strings/ : localization data
res/values/styles.xml |
<resources> ... <style name="MyFontStyle"> <item name="android:textColor">#FF00FF</item> <item name="android:padding">30dp</item> </style>
</resources>
|
activity_main.xml |
<LinearLayout ...>
<TextView style="@style/MyFontStyle" ... /> ...
</LinearLayout>
|
- Themes : 여러 스타일의 집합