24 | -s svm_type: set type of SVM (default 0)
25 | 0 -- C-SVC
26 | 1 -- nu-SVC
27 | 2 -- one-class SVM
28 | 3 -- epsilon-SVR
29 | 4 -- nu-SVR
30 |
31 | -t kernel_type: set type of kernel function (default 2)
32 | 0 -- linear: u'*v
33 | 1 -- polynomial: (gamma*u'*v + coef0)^degree
34 | 2 -- radial basis function: exp(-gamma*|u-v|^2)
35 | 3 -- sigmoid: tanh(gamma*u'*v + coef0)
36 |
37 | -d degree: set degree in kernel function (default 3)
38 |
39 | -g gamma: set gamma in kernel function (default 1/num_features)
40 |
41 | -r coef0: set coef0 in kernel function (default 0)
42 |
43 | -c cost: set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
44 |
45 | -n nu: set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
46 |
47 | -p epsilon: set the epsilon in loss function of epsilon-SVR (default 0.1)
48 |
49 | -m cachesize: set cache memory size in MB (default 100)
50 |
51 | -e epsilon: set tolerance of termination criterion (default 0.001)
52 |
53 | -h shrinking: whether to use the shrinking heuristics, 0 or 1 (default 1)
54 |
55 | -b probability_estimates: whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)
56 |
57 | -wi weight: set the parameter C of class i to weight*C, for C-SVC (default 1)
58 |
59 | The k in the -g option means the number of attributes in the input data.
60 |
20 | Copyright (c) 2000-2017 Chih-Chung Chang and Chih-Jen Lin
21 | All rights reserved.
22 |
23 | Redistribution and use in source and binary forms, with or without
24 | modification, are permitted provided that the following conditions
25 | are met:
26 |
27 | 1. Redistributions of source code must retain the above copyright
28 | notice, this list of conditions and the following disclaimer.
29 |
30 | 2. Redistributions in binary form must reproduce the above copyright
31 | notice, this list of conditions and the following disclaimer in the
32 | documentation and/or other materials provided with the distribution.
33 |
34 | 3. Neither name of copyright holders nor the names of its contributors
35 | may be used to endorse or promote products derived from this software
36 | without specific prior written permission.
37 |
38 |
39 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
40 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
41 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
42 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
43 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
45 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
46 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
47 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
48 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
49 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 |
51 |
FileBrowser v1.4
52 |
53 | MIT License
54 |
55 | Copyright (c) 2017 adityak368
56 |
57 | Permission is hereby granted, free of charge, to any person obtaining a copy
58 | of this software and associated documentation files (the "Software"), to deal
59 | in the Software without restriction, including without limitation the rights
60 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
61 | copies of the Software, and to permit persons to whom the Software is
62 | furnished to do so, subject to the following conditions:
63 |
64 | The above copyright notice and this permission notice shall be included in all
65 | copies or substantial portions of the Software.
66 |
67 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
73 | SOFTWARE.
74 |
75 |
Gota v1.4.1
76 |
77 | Copyright (c) 2015 Abdullah Alhazmy
78 |
79 | Licensed under the Apache License, Version 2.0 (the "License");
80 | you may not use this file except in compliance with the License.
81 | You may obtain a copy of the License at
82 |
83 | http://www.apache.org/licenses/LICENSE-2.0
84 |
85 | Unless required by applicable law or agreed to in writing, software
86 | distributed under the License is distributed on an "AS IS" BASIS,
87 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
88 | See the License for the specific language governing permissions and
89 | limitations under the License.
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/Example/app/src/main/java/com/test/libsvmandroidexample/ContainerActivity.java:
--------------------------------------------------------------------------------
1 | package com.test.libsvmandroidexample;
2 |
3 | import android.Manifest;
4 | import android.app.AlertDialog;
5 | import android.content.DialogInterface;
6 | import android.content.pm.PackageManager;
7 | import android.content.res.AssetManager;
8 | import android.os.Bundle;
9 | import android.os.Environment;
10 | import android.support.annotation.NonNull;
11 | import android.support.design.widget.TabLayout;
12 | import android.support.v4.app.Fragment;
13 | import android.support.v4.app.FragmentManager;
14 | import android.support.v4.app.FragmentPagerAdapter;
15 | import android.support.v4.content.ContextCompat;
16 | import android.support.v4.view.ViewPager;
17 | import android.support.v7.app.AppCompatActivity;
18 | import android.support.v7.widget.Toolbar;
19 | import android.util.Log;
20 | import android.view.LayoutInflater;
21 | import android.view.Menu;
22 | import android.view.MenuItem;
23 | import android.view.View;
24 | import android.webkit.WebView;
25 | import android.widget.Toast;
26 | import net.alhazmy13.gota.Gota;
27 | import net.alhazmy13.gota.GotaResponse;
28 | import java.io.File;
29 | import java.io.FileOutputStream;
30 | import java.io.IOException;
31 | import java.io.InputStream;
32 | import java.io.OutputStream;
33 | import java.util.ArrayList;
34 | import java.util.List;
35 |
36 |
37 | public class ContainerActivity extends AppCompatActivity implements Gota.OnRequestPermissionsBack {
38 |
39 | public static final String TAG = "LibSVMExample";
40 | public static final String processId = Integer.toString(android.os.Process.myPid());
41 |
42 | private Toolbar toolbar;
43 | private TabLayout tabLayout;
44 | private ViewPager viewPager;
45 | public static String appFolderPath;
46 | public static String systemPath;
47 |
48 | @Override
49 | protected void onCreate(Bundle savedInstanceState) {
50 | super.onCreate(savedInstanceState);
51 | setContentView(R.layout.activity_container);
52 | toolbar = (Toolbar) findViewById(R.id.toolbar);
53 | setSupportActionBar(toolbar);
54 | viewPager = (ViewPager) findViewById(R.id.viewpager);
55 | setupViewPager(viewPager);
56 | tabLayout = (TabLayout) findViewById(R.id.tabs);
57 | tabLayout.setupWithViewPager(viewPager);
58 | final boolean readStorage = canReadExternalStorage();
59 | final boolean writeStorage = canWriteExternalStorage();
60 | // request app permissions
61 | if (!readStorage || !writeStorage){
62 | new Gota.Builder(this)
63 | .withPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_LOGS)
64 | .requestId(1)
65 | .setListener(this)
66 | .check();
67 | }
68 | systemPath = Environment.getExternalStorageDirectory() + "/";
69 | appFolderPath = systemPath+"LibSVMAssets/";
70 |
71 | // create assets folder if it doesn't exist
72 | createAssetsFolder();
73 |
74 | // copy all data files from assets to external storage
75 | try {
76 | String[] list = getAssets().list("data");
77 | for (String file: list) {
78 | copyToExternalStorage(file, "data");
79 | }
80 | } catch (IOException e) {
81 | e.printStackTrace();
82 | }
83 | }
84 |
85 | private void setupViewPager(ViewPager viewPager) {
86 | ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
87 | adapter.addFragment(new ScaleFragment(), "Scale");
88 | adapter.addFragment(new TrainFragment(), "Train");
89 | adapter.addFragment(new PredictFragment(), "Predict");
90 | viewPager.setAdapter(adapter);
91 | }
92 |
93 | @Override
94 | public void onRequestBack(int requestId, @NonNull GotaResponse gotaResponse) {
95 | if (gotaResponse.isDenied(Manifest.permission.READ_EXTERNAL_STORAGE)){
96 | Toast.makeText(this, "READ_EXTERNAL_STORAGE permission is required for the app to function properly.", Toast.LENGTH_LONG).show();
97 | }
98 | if (gotaResponse.isDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)){
99 | Toast.makeText(this, "WRITE_EXTERNAL_STORAGE permission is required for the app to function properly.", Toast.LENGTH_LONG).show();
100 | }
101 | if (gotaResponse.isGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE) || gotaResponse.isGranted(Manifest.permission.READ_EXTERNAL_STORAGE)){
102 | Toast.makeText(this, "Restart the app to able to use the newly granted permissions.", Toast.LENGTH_LONG).show();
103 | }
104 | }
105 |
106 | @Override
107 | public boolean onCreateOptionsMenu(Menu menu) {
108 | getMenuInflater().inflate(R.menu.main_menu, menu);
109 | return super.onCreateOptionsMenu(menu);
110 | }
111 |
112 | @Override
113 | public boolean onOptionsItemSelected(MenuItem item) {
114 | switch (item.getItemId()){
115 | case R.id.menu_copyright_btn:
116 | // show copyright dialog
117 | showDialog("copyright");
118 | return true;
119 | case R.id.menu_train_options:
120 | // show train options dialog
121 | showDialog("Train_Options");
122 | return true;
123 | case R.id.menu_scale_options:
124 | // show scale options dialog
125 | showDialog("Scale_Options");
126 | return true;
127 | case R.id.menu_predict_options:
128 | // show train options dialog
129 | showDialog("Predict_Options");
130 | return true;
131 | default:
132 | return super.onOptionsItemSelected(item);
133 | }
134 | }
135 |
136 | public void showDialog(String htmlFile){
137 | LayoutInflater li = LayoutInflater.from(this);
138 | View promptsView = li.inflate(R.layout.dialog_layout, null);
139 | AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this)
140 | .setTitle((htmlFile.contains("_") ? htmlFile.replace("_", " ") : htmlFile))
141 | .setView(promptsView)
142 | .setNeutralButton("Ok", new DialogInterface.OnClickListener() {
143 | @Override
144 | public void onClick(DialogInterface dialog, int which) {
145 | dialog.dismiss();
146 | }
147 | });
148 | final WebView webview = (WebView) promptsView.findViewById(R.id.webview);
149 | webview.loadUrl("file:///android_asset/html/"+htmlFile+".html");
150 | final AlertDialog alertDialog = alertDialogBuilder.create();
151 | alertDialog.show();
152 | }
153 |
154 | private class ViewPagerAdapter extends FragmentPagerAdapter {
155 | private final List mFragmentList = new ArrayList<>();
156 | private final List mFragmentTitleList = new ArrayList<>();
157 |
158 | public ViewPagerAdapter(FragmentManager manager) {
159 | super(manager);
160 | }
161 |
162 | @Override
163 | public Fragment getItem(int position) {
164 | return mFragmentList.get(position);
165 | }
166 |
167 | @Override
168 | public int getCount() {
169 | return mFragmentList.size();
170 | }
171 |
172 | public void addFragment(Fragment fragment, String title) {
173 | mFragmentList.add(fragment);
174 | mFragmentTitleList.add(title);
175 | }
176 |
177 | @Override
178 | public CharSequence getPageTitle(int position) {
179 | return mFragmentTitleList.get(position);
180 | }
181 | }
182 |
183 | public boolean canReadExternalStorage(){
184 | int permissionStatus = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE);
185 | if (permissionStatus == PackageManager.PERMISSION_GRANTED){
186 | return true;
187 | } else {
188 | return false;
189 | }
190 | }
191 |
192 | public boolean canWriteExternalStorage(){
193 | int permissionStatus = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
194 | if (permissionStatus == PackageManager.PERMISSION_GRANTED){
195 | return true;
196 | } else {
197 | return false;
198 | }
199 | }
200 |
201 | private void createAssetsFolder(){
202 | // create app assets folder if not created
203 | File folder = new File(appFolderPath);
204 |
205 | if (!folder.exists()) {
206 | Log.d(TAG,"LibSVMAssets folder does not exist, creating one");
207 | folder.mkdirs();
208 | } else {
209 | Log.w(TAG,"INFO: LibSVMAssets folder already exists.");
210 | }
211 | }
212 |
213 | private void copyToExternalStorage(String assetName, String assetsDirectory){
214 | String from = assetName;
215 | String to = appFolderPath+from;
216 |
217 | // check if the file exists
218 | File file = new File(to);
219 | if(file.exists()){
220 | Log.d(TAG, "copyToExternalStorage: file already exist, no need to copy: "+from);
221 | } else {
222 | // do copy
223 | boolean copyResult = copyAsset(getAssets(), from, assetsDirectory, to);
224 | Log.d(TAG, "copyToExternalStorage: isCopied -> "+copyResult);
225 | }
226 | }
227 |
228 | private boolean copyAsset(AssetManager assetManager, String fromAssetPath, String assetsDirectory, String toPath) {
229 | InputStream inputStream = null;
230 | OutputStream outputStream = null;
231 | try {
232 | inputStream = assetManager.open(assetsDirectory+"/"+fromAssetPath);
233 | new File(toPath).createNewFile();
234 | outputStream = new FileOutputStream(toPath);
235 | copyFile(inputStream, outputStream);
236 | inputStream.close();
237 | outputStream.flush();
238 | outputStream.close();
239 | return true;
240 | } catch(Exception e) {
241 | e.printStackTrace();
242 | Log.e(TAG, "copyAsset: unable to copy file: "+fromAssetPath);
243 | return false;
244 | }
245 | }
246 |
247 | private void copyFile(InputStream inputStream, OutputStream outputStream) throws IOException {
248 | byte[] buffer = new byte[1024];
249 | int read;
250 | while((read = inputStream.read(buffer)) != -1){
251 | outputStream.write(buffer, 0, read);
252 | }
253 | }
254 |
255 | }
--------------------------------------------------------------------------------
/Example/app/src/main/java/com/test/libsvmandroidexample/PredictFragment.java:
--------------------------------------------------------------------------------
1 | package com.test.libsvmandroidexample;
2 |
3 | import android.app.Activity;
4 | import android.app.ProgressDialog;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.AsyncTask;
8 | import android.os.Bundle;
9 | import android.support.v4.app.Fragment;
10 | import android.text.TextUtils;
11 | import android.util.Log;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.widget.Button;
16 | import android.widget.CheckBox;
17 | import android.widget.CompoundButton;
18 | import android.widget.EditText;
19 | import android.widget.Toast;
20 |
21 | import com.aditya.filebrowser.Constants;
22 | import com.aditya.filebrowser.FileChooser;
23 |
24 | import java.util.ArrayList;
25 | import java.util.List;
26 |
27 | import umich.cse.yctung.androidlibsvm.LibSVM;
28 |
29 |
30 | public class PredictFragment extends Fragment {
31 |
32 | ProgressDialog progressDialog;
33 | public static int PICK_TESTFILE = 3000;
34 | public static int PICK_MODELFILE = 3001;
35 | Button predictButton;
36 | Button testFilePicker;
37 | Button modelFilePicker;
38 | EditText outputFileNameInput;
39 | EditText probabilityInput;
40 | CheckBox probabilityCheckbox;
41 |
42 |
43 | public PredictFragment() {
44 | // Required empty public constructor
45 | }
46 |
47 | @Override
48 | public void onCreate(Bundle savedInstanceState) {
49 | super.onCreate(savedInstanceState);
50 | }
51 |
52 | @Override
53 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
54 | Bundle savedInstanceState) {
55 | // Inflate the layout for this fragment
56 | View view = inflater.inflate(R.layout.fragment_predict, container, false);
57 | progressDialog = new ProgressDialog(getContext());
58 | testFilePicker = (Button) view.findViewById(R.id.testfilepicker);
59 | modelFilePicker = (Button) view.findViewById(R.id.modelfilepicker);
60 | predictButton = (Button) view.findViewById(R.id.predict_btn);
61 | outputFileNameInput = (EditText) view.findViewById(R.id.output_filename);
62 | probabilityInput = (EditText) view.findViewById(R.id.probabilityinput);
63 | probabilityCheckbox = (CheckBox) view.findViewById(R.id.probabilitycheckbox);
64 | probabilityCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
65 | @Override
66 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
67 | if (isChecked){
68 | probabilityInput.setEnabled(true);
69 | } else {
70 | probabilityInput.setEnabled(false);
71 | }
72 | }
73 | });
74 | testFilePicker.setOnClickListener(new View.OnClickListener() {
75 | @Override
76 | public void onClick(View v) {
77 | Intent i2 = new Intent(getContext(), FileChooser.class);
78 | i2.putExtra(Constants.SELECTION_MODE, Constants.SELECTION_MODES.SINGLE_SELECTION.ordinal());
79 | startActivityForResult(i2, PICK_TESTFILE);
80 | }
81 | });
82 | modelFilePicker.setOnClickListener(new View.OnClickListener() {
83 | @Override
84 | public void onClick(View v) {
85 | Intent i2 = new Intent(getContext(), FileChooser.class);
86 | i2.putExtra(Constants.SELECTION_MODE, Constants.SELECTION_MODES.SINGLE_SELECTION.ordinal());
87 | startActivityForResult(i2, PICK_MODELFILE);
88 | }
89 | });
90 | predictButton.setOnClickListener(new View.OnClickListener() {
91 | @Override
92 | public void onClick(View v) {
93 | List commands = new ArrayList<>();
94 | if (probabilityCheckbox.isChecked()){
95 | if (!Utility.isEmptyOrWhitespace(probabilityInput.getText().toString())){
96 | commands.add("-b");
97 | commands.add(probabilityInput.getText().toString());
98 | }
99 | }
100 | commands.add(testFilePicker.getText().toString());
101 | commands.add(modelFilePicker.getText().toString());
102 | if (Utility.isEmptyOrWhitespace(outputFileNameInput.getText().toString())) {
103 | Toast.makeText(getContext(), "Output file name is required!", Toast.LENGTH_SHORT).show();
104 | return;
105 | }
106 | commands.add(ContainerActivity.appFolderPath+outputFileNameInput.getText().toString());
107 | new AsyncPredictTask().execute(commands.toArray(new String[0]));
108 | }
109 | });
110 | return view;
111 | }
112 |
113 | @Override
114 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
115 | super.onActivityResult(requestCode, resultCode, data);
116 | if (requestCode == PICK_TESTFILE && data != null) {
117 | if (resultCode == Activity.RESULT_OK) {
118 | Uri file = data.getData();
119 | testFilePicker.setText(file.getPath());
120 | }
121 | }
122 | if (requestCode == PICK_MODELFILE && data != null) {
123 | if (resultCode == Activity.RESULT_OK) {
124 | Uri file = data.getData();
125 | modelFilePicker.setText(file.getPath());
126 | }
127 | }
128 | }
129 |
130 | private class AsyncPredictTask extends AsyncTask
131 | {
132 | @Override
133 | protected void onPreExecute() {
134 | super.onPreExecute();
135 | progressDialog.setTitle("SVM Predict");
136 | progressDialog.setMessage("Executing svm-predict, please wait...");
137 | progressDialog.show();
138 | Log.d(ContainerActivity.TAG, "==================\nStart of SVM PREDICT\n==================");
139 | }
140 |
141 | @Override
142 | protected Void doInBackground(String... params) {
143 | LibSVM.getInstance().predict(TextUtils.join(" ", params));
144 | return null;
145 | }
146 | @Override
147 | protected void onPostExecute(Void result) {
148 | progressDialog.dismiss();
149 | Toast.makeText(getContext(), "SVM Predict has executed successfully!", Toast.LENGTH_LONG).show();
150 | Log.d(ContainerActivity.TAG, "==================\nEnd of SVM PREDICT\n==================");
151 | Utility.readLogcat(getContext(), "SVM-Predict Results");
152 | }
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/Example/app/src/main/java/com/test/libsvmandroidexample/ScaleFragment.java:
--------------------------------------------------------------------------------
1 | package com.test.libsvmandroidexample;
2 |
3 | import android.app.Activity;
4 | import android.app.ProgressDialog;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.AsyncTask;
8 | import android.os.Bundle;
9 | import android.support.v4.app.Fragment;
10 | import android.text.TextUtils;
11 | import android.util.Log;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.widget.Button;
16 | import android.widget.CheckBox;
17 | import android.widget.CompoundButton;
18 | import android.widget.EditText;
19 | import android.widget.Toast;
20 |
21 | import com.aditya.filebrowser.Constants;
22 | import com.aditya.filebrowser.FileChooser;
23 |
24 | import java.util.ArrayList;
25 | import java.util.List;
26 |
27 | import umich.cse.yctung.androidlibsvm.LibSVM;
28 |
29 |
30 | public class ScaleFragment extends Fragment {
31 |
32 | ProgressDialog progressDialog;
33 | public static int PICK_DATAFILE = 1000;
34 | public static int PICK_RESTOREFILE = 1001;
35 | Button dataFilePicker;
36 | Button restoreFilePicker;
37 | Button scaleButton;
38 | CheckBox saveFileNameCheckBox;
39 | CheckBox restoreFileNameCheckbox;
40 | CheckBox xLowerCheckBox;
41 | CheckBox xUpperCheckBox;
42 | CheckBox yLimitsCheckBox;
43 | EditText saveFileNameInput;
44 | EditText xLowerLimitInput;
45 | EditText xUpperLimitInput;
46 | EditText yLimitsInput;
47 | EditText outputFileNameInput;
48 |
49 |
50 | public ScaleFragment() {
51 | // Required empty public constructor
52 | }
53 |
54 | @Override
55 | public void onCreate(Bundle savedInstanceState) {
56 | super.onCreate(savedInstanceState);
57 | }
58 |
59 | @Override
60 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
61 | Bundle savedInstanceState) {
62 | // Inflate the layout for this fragment
63 | final View view = inflater.inflate(R.layout.fragment_scale, container, false);
64 | progressDialog = new ProgressDialog(getContext());
65 |
66 | // Buttons
67 | dataFilePicker = (Button) view.findViewById(R.id.datafilepicker);
68 | restoreFilePicker = (Button) view.findViewById(R.id.restorefilepicker);
69 | scaleButton = (Button) view.findViewById(R.id.scale_btn);
70 |
71 | // EditTexts
72 | saveFileNameInput = (EditText) view.findViewById(R.id.save_filename);
73 | outputFileNameInput = (EditText) view.findViewById(R.id.output_filename);
74 | xLowerLimitInput = (EditText) view.findViewById(R.id.lowerlimit);
75 | xUpperLimitInput = (EditText) view.findViewById(R.id.upperlimit);
76 | yLimitsInput = (EditText) view.findViewById(R.id.ylimit);
77 |
78 | // CheckBoxes
79 | saveFileNameCheckBox = (CheckBox) view.findViewById(R.id.savecheckBox);
80 | restoreFileNameCheckbox = (CheckBox) view.findViewById(R.id.restorecheckBox);
81 | xLowerCheckBox = (CheckBox) view.findViewById(R.id.lowerlimitcheckbox);
82 | xUpperCheckBox = (CheckBox) view.findViewById(R.id.upperlimitcheckbox);
83 | yLimitsCheckBox = (CheckBox) view.findViewById(R.id.ylimitcheckbox);
84 |
85 | // Listeners
86 | dataFilePicker.setOnClickListener(new View.OnClickListener() {
87 | @Override
88 | public void onClick(View v) {
89 | Intent i2 = new Intent(getContext(), FileChooser.class);
90 | i2.putExtra(Constants.SELECTION_MODE, Constants.SELECTION_MODES.SINGLE_SELECTION.ordinal());
91 | startActivityForResult(i2, PICK_DATAFILE);
92 | }
93 | });
94 | restoreFilePicker.setOnClickListener(new View.OnClickListener() {
95 | @Override
96 | public void onClick(View v) {
97 | Intent i2 = new Intent(getContext(), FileChooser.class);
98 | i2.putExtra(Constants.SELECTION_MODE, Constants.SELECTION_MODES.SINGLE_SELECTION.ordinal());
99 | startActivityForResult(i2, PICK_RESTOREFILE);
100 | }
101 | });
102 | saveFileNameCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
103 | @Override
104 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
105 | if (isChecked){
106 | saveFileNameInput.setEnabled(true);
107 | restoreFileNameCheckbox.setChecked(false);
108 | } else {
109 | saveFileNameInput.setEnabled(false);
110 | }
111 | }
112 | });
113 | restoreFileNameCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
114 | @Override
115 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
116 | if (isChecked){
117 | restoreFilePicker.setEnabled(true);
118 | saveFileNameCheckBox.setChecked(false);
119 | } else {
120 | restoreFilePicker.setEnabled(false);
121 | }
122 | }
123 | });
124 | xLowerCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
125 | @Override
126 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
127 | if (isChecked){
128 | xLowerLimitInput.setEnabled(true);
129 | yLimitsCheckBox.setChecked(false);
130 | } else {
131 | xLowerLimitInput.setEnabled(false);
132 | }
133 | }
134 | });
135 | xUpperCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
136 | @Override
137 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
138 | if (isChecked){
139 | xUpperLimitInput.setEnabled(true);
140 | yLimitsCheckBox.setChecked(false);
141 | } else {
142 | xUpperLimitInput.setEnabled(false);
143 | }
144 | }
145 | });
146 | yLimitsCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
147 | @Override
148 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
149 | if (isChecked){
150 | yLimitsInput.setEnabled(true);
151 | xLowerCheckBox.setChecked(false);
152 | xUpperCheckBox.setChecked(false);
153 | } else {
154 | yLimitsInput.setEnabled(false);
155 | }
156 | }
157 | });
158 | scaleButton.setOnClickListener(new View.OnClickListener() {
159 | @Override
160 | public void onClick(View v) {
161 | List options = new ArrayList<>();
162 | String dataFilePath = dataFilePicker.getText().toString();
163 | String outputFileName = outputFileNameInput.getText().toString();
164 | if (xLowerCheckBox.isChecked() || xUpperCheckBox.isChecked()){
165 | if (xLowerCheckBox.isChecked()){
166 | if (!Utility.isEmptyOrWhitespace(xLowerLimitInput.getText().toString())){
167 | options.add("-l");
168 | options.add(xLowerLimitInput.getText().toString());
169 | }
170 | }
171 | if (xUpperCheckBox.isChecked()){
172 | if (!Utility.isEmptyOrWhitespace(xUpperLimitInput.getText().toString())){
173 | options.add("-u");
174 | options.add(xUpperLimitInput.getText().toString());
175 | }
176 | }
177 | } else if (yLimitsCheckBox.isChecked()){
178 | if (!Utility.isEmptyOrWhitespace(yLimitsInput.getText().toString())){
179 | options.add("-y");
180 | options.add(yLimitsInput.getText().toString());
181 | }
182 | }
183 | if (saveFileNameCheckBox.isChecked()) {
184 | String saveFileName = saveFileNameInput.getText().toString();
185 | if (!Utility.isEmptyOrWhitespace(saveFileName)){
186 | options.add("-s");
187 | options.add(ContainerActivity.appFolderPath+saveFileName);
188 | }
189 | } else if (restoreFileNameCheckbox.isChecked()){
190 | options.add("-r");
191 | options.add(restoreFilePicker.getText().toString());
192 | }
193 | options.add(dataFilePath);
194 | String optionsString = TextUtils.join(" ", options);
195 | String outputFilePath = null;
196 | if (Utility.isEmptyOrWhitespace(outputFileName)) {
197 | Toast.makeText(getContext(), "Output file name is required!", Toast.LENGTH_SHORT).show();
198 | return;
199 | }
200 | outputFilePath = ContainerActivity.appFolderPath+outputFileName;
201 | new AsyncScaleTask().execute(new String[]{optionsString, outputFilePath});
202 | }
203 | });
204 | return view;
205 | }
206 |
207 | @Override
208 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
209 | super.onActivityResult(requestCode, resultCode, data);
210 | if (requestCode == PICK_DATAFILE && data != null) {
211 | if (resultCode == Activity.RESULT_OK) {
212 | Uri file = data.getData();
213 | dataFilePicker.setText(file.getPath());
214 | }
215 | }
216 | if (requestCode == PICK_RESTOREFILE && data != null) {
217 | if (resultCode == Activity.RESULT_OK) {
218 | Uri file = data.getData();
219 | restoreFilePicker.setText(file.getPath());
220 | }
221 | }
222 | }
223 |
224 |
225 | private class AsyncScaleTask extends AsyncTask
226 | {
227 | @Override
228 | protected void onPreExecute() {
229 | super.onPreExecute();
230 | progressDialog.setTitle("SVM Scale");
231 | progressDialog.setMessage("Executing svm-scale, please wait...");
232 | progressDialog.show();
233 | Log.d(ContainerActivity.TAG, "==================\nStart of SVM SCALE\n==================");
234 | }
235 |
236 | @Override
237 | protected Void doInBackground(String... params) {
238 | LibSVM.getInstance().scale(params[0], params[1]);
239 | return null;
240 | }
241 | @Override
242 | protected void onPostExecute(Void result) {
243 | progressDialog.dismiss();
244 | Toast.makeText(getContext(), "SVM Scale has executed successfully!", Toast.LENGTH_LONG).show();
245 | Log.d(ContainerActivity.TAG, "==================\nEnd of SVM SCALE\n==================");
246 | Utility.readLogcat(getContext(), "SVM-Scale Results");
247 | }
248 | }
249 | }
--------------------------------------------------------------------------------
/Example/app/src/main/java/com/test/libsvmandroidexample/TrainFragment.java:
--------------------------------------------------------------------------------
1 | package com.test.libsvmandroidexample;
2 |
3 | import android.app.Activity;
4 | import android.app.ProgressDialog;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.AsyncTask;
8 | import android.os.Bundle;
9 | import android.support.v4.app.Fragment;
10 | import android.text.TextUtils;
11 | import android.util.Log;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.widget.Button;
16 | import android.widget.EditText;
17 | import android.widget.Toast;
18 |
19 | import com.aditya.filebrowser.Constants;
20 | import com.aditya.filebrowser.FileChooser;
21 |
22 | import umich.cse.yctung.androidlibsvm.LibSVM;
23 |
24 |
25 | public class TrainFragment extends Fragment {
26 |
27 | ProgressDialog progressDialog;
28 | public static int PICK_DATAFILE = 2000;
29 | Button trainButton;
30 | Button dataFilePicker;
31 | EditText outputFileInput;
32 | EditText commandInput;
33 |
34 |
35 | public TrainFragment() {
36 | // Required empty public constructor
37 | }
38 |
39 | @Override
40 | public void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | }
43 |
44 | @Override
45 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
46 | Bundle savedInstanceState) {
47 | View view = inflater.inflate(R.layout.fragment_train, container, false);
48 | progressDialog = new ProgressDialog(getContext());
49 | trainButton = (Button) view.findViewById(R.id.train_btn);
50 | dataFilePicker = (Button) view.findViewById(R.id.datafilepicker);
51 | outputFileInput = (EditText) view.findViewById(R.id.output_filename);
52 | commandInput = (EditText) view.findViewById(R.id.train_options);
53 | trainButton.setOnClickListener(new View.OnClickListener() {
54 | @Override
55 | public void onClick(View v) {
56 | if (Utility.isEmptyOrWhitespace(outputFileInput.getText().toString()) || Utility.isEmptyOrWhitespace(commandInput.getText().toString())) {
57 | Toast.makeText(getContext(), "All fields are required!", Toast.LENGTH_SHORT).show();
58 | return;
59 | }
60 | String outputModelPath = ContainerActivity.appFolderPath+outputFileInput.getText().toString();
61 | String commandString = commandInput.getText().toString();
62 | String dataFilePath = dataFilePicker.getText().toString();
63 | new AsyncTrainTask().execute(new String[]{commandString, dataFilePath, outputModelPath});
64 | }
65 | });
66 | dataFilePicker.setOnClickListener(new View.OnClickListener() {
67 | @Override
68 | public void onClick(View v) {
69 | Intent i2 = new Intent(getContext(), FileChooser.class);
70 | i2.putExtra(Constants.SELECTION_MODE, Constants.SELECTION_MODES.SINGLE_SELECTION.ordinal());
71 | startActivityForResult(i2, PICK_DATAFILE);
72 | }
73 | });
74 | return view;
75 | }
76 |
77 | @Override
78 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
79 | super.onActivityResult(requestCode, resultCode, data);
80 | if (requestCode == PICK_DATAFILE && data != null) {
81 | if (resultCode == Activity.RESULT_OK) {
82 | Uri file = data.getData();
83 | dataFilePicker.setText(file.getPath());
84 | }
85 | }
86 | }
87 |
88 | private class AsyncTrainTask extends AsyncTask
89 | {
90 | @Override
91 | protected void onPreExecute() {
92 | super.onPreExecute();
93 | progressDialog.setTitle("SVM Train");
94 | progressDialog.setMessage("Executing svm-train, please wait...");
95 | progressDialog.show();
96 | Log.d(ContainerActivity.TAG, "==================\nStart of SVM TRAIN\n==================");
97 | }
98 |
99 | @Override
100 | protected Void doInBackground(String... params) {
101 | LibSVM.getInstance().train(TextUtils.join(" ", params));
102 | return null;
103 | }
104 | @Override
105 | protected void onPostExecute(Void result) {
106 | progressDialog.dismiss();
107 | Toast.makeText(getContext(), "SVM Train has executed successfully!", Toast.LENGTH_LONG).show();
108 | Log.d(ContainerActivity.TAG, "==================\nEnd of SVM TRAIN\n==================");
109 | Utility.readLogcat(getContext(), "SVM-Train Results");
110 | }
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/Example/app/src/main/java/com/test/libsvmandroidexample/Utility.java:
--------------------------------------------------------------------------------
1 | package com.test.libsvmandroidexample;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.util.Log;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.widget.TextView;
10 |
11 | import java.io.BufferedReader;
12 | import java.io.IOException;
13 | import java.io.InputStreamReader;
14 |
15 | public class Utility {
16 |
17 | public static boolean isEmptyOrWhitespace(String str){
18 | if (str.isEmpty() || str.trim().isEmpty())
19 | return true;
20 | else
21 | return false;
22 | }
23 |
24 | public static void readLogcat(Context context, String title){
25 | try {
26 | Process process = Runtime.getRuntime().exec("logcat -d");
27 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
28 | StringBuilder log = new StringBuilder();
29 | String line = "";
30 | while ((line = bufferedReader.readLine()) != null) {
31 | if (line.contains(ContainerActivity.processId) && line.contains("LibSvm")) {
32 | if (line.contains("=======")){
33 | log.append("==================\n");
34 | } else if (line.contains("Start of SVM")){
35 | log.append(line.substring(line.indexOf("Start"))+"\n");
36 | } else if (line.contains("End of SVM")) {
37 | log.append(line.substring(line.indexOf("End"))+"\n");
38 | } else {
39 | int indexOfProcessId = line.lastIndexOf(ContainerActivity.processId);
40 | String newLine = line.substring(indexOfProcessId);
41 | log.append(newLine+"\n\n");
42 | }
43 | }
44 | }
45 | showResult(context, log.toString(), title);
46 |
47 | } catch (IOException e) {
48 | e.printStackTrace();
49 | Log.e(ContainerActivity.TAG, "readLogcat: failed to read from logcat logger.");
50 | }
51 | }
52 |
53 | public static void showResult(Context context, String resultText, String title){
54 | LayoutInflater li = LayoutInflater.from(context);
55 | View promptsView = li.inflate(R.layout.dialog_result, null);
56 | AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context)
57 | .setTitle(title)
58 | .setView(promptsView)
59 | .setNeutralButton("Ok", new DialogInterface.OnClickListener() {
60 | @Override
61 | public void onClick(DialogInterface dialog, int which) {
62 | dialog.dismiss();
63 | }
64 | });
65 | final TextView resultTextView = (TextView) promptsView.findViewById(R.id.resulttextview);
66 | resultTextView.setText(resultText);
67 | final AlertDialog alertDialog = alertDialogBuilder.create();
68 | alertDialog.show();
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/layout/activity_container.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
19 |
20 |
26 |
27 |
28 |
33 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/layout/dialog_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/layout/dialog_result.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/layout/fragment_predict.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
19 |
20 |
25 |
26 |
31 |
32 |
38 |
39 |
44 |
45 |
50 |
51 |
57 |
58 |
70 |
71 |
77 |
78 |
91 |
92 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/layout/fragment_scale.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
15 |
16 |
22 |
23 |
28 |
29 |
34 |
35 |
41 |
42 |
54 |
55 |
60 |
61 |
67 |
68 |
81 |
82 |
88 |
89 |
95 |
96 |
101 |
102 |
112 |
113 |
118 |
119 |
124 |
125 |
131 |
132 |
145 |
146 |
147 |
148 |
153 |
154 |
160 |
161 |
174 |
175 |
176 |
177 |
178 |
179 |
189 |
190 |
194 |
200 |
201 |
214 |
215 |
216 |
217 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/layout/fragment_train.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
19 |
20 |
25 |
26 |
31 |
32 |
38 |
39 |
51 |
52 |
58 |
59 |
71 |
72 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/menu/main_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Example/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #125688
4 | #104a74
5 | #FFFFFF
6 | #FFFFFF
7 | #000000
8 | #c8e8ff
9 | #009688
10 | #00796B
11 | #B2DFDB
12 | #FF9800
13 | #212121
14 | #cbcbcb
15 | #FFFFFF
16 | #BDBDBD
17 |
18 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 | 264dp
7 | 16dp
8 | 14sp
9 | 72dp
10 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LibSVM Android
3 |
4 |
5 |
6 | Hello blank fragment
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Example/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.3'
9 | // NOTE: Do not place your application dependencies here; they belong
10 | // in the individual module build.gradle files
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | jcenter()
17 | }
18 | }
19 |
20 | task clean(type: Delete) {
21 | delete rootProject.buildDir
22 | }
23 |
--------------------------------------------------------------------------------
/Example/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/Example/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Example/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun May 28 15:45:43 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/Example/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/Example/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/Example/screenshots/demo_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/screenshots/demo_all.png
--------------------------------------------------------------------------------
/Example/screenshots/demo_predict.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/screenshots/demo_predict.png
--------------------------------------------------------------------------------
/Example/screenshots/demo_scale.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/screenshots/demo_scale.png
--------------------------------------------------------------------------------
/Example/screenshots/demo_train.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Example/screenshots/demo_train.png
--------------------------------------------------------------------------------
/Example/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':androidlibsvm-release'
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AndroidLibSvm
2 | An open-source Android AAR library of the famous [LibSVM](https://www.csie.ntu.edu.tw/~cjlin/libsvm/)
3 |
4 | ## Update
5 | - 2017/09/26: Build to AAR, so users don't need to worry about JNI/NDK
6 | - 2017/09/27: Thank [Isaac Salem](https://github.com/iamAyezak) for sharing his app using AndroidLibSVM
7 | 
8 |
9 | ## Getting Started
10 |
11 | ### Prerequisites
12 | AndroidStudio (I am using 2.3.3 + Gradle 2.2.3, but it should be ok for other versions)
13 |
14 | ### Install
15 | Install is easy, you just import our [AAR library](/Release/) into your Android project by the following steps:
16 |
17 | ```
18 | Right-click your module -> new -> module -> Import .JAR/.AAR Package -> select our Release/androidlibsvm-release.aar
19 | ```
20 |
21 | After this, you should add the app dependency by:
22 |
23 | ```
24 | Right-click your app module -> open module setting -> clieck your app -> dependencies -> + -> module dependency -> androidlibsvm
25 | ```
26 |
27 | Once you finish these two steps, you should be able to import our LibSVM class in your JAVA code by:
28 |
29 | ```
30 | import umich.cse.yctung.androidlibsvm.LibSVM;
31 | ```
32 |
33 | If you get any AAR import issue, please read this [Android official AAR guide](https://developer.android.com/studio/projects/android-library.html).
34 |
35 | ### Usage
36 | You can initialize our LibSVM class either by
37 |
38 | ```
39 | LibSVM svm = new LibSVM();
40 | ```
41 |
42 | or
43 |
44 | ```
45 | LibSVM svm = LibSVM().getInstance();
46 | ```
47 |
48 | Our implementation uses **files** as an input/output interface (just like how the original LibSVM works on the shell). So if you are familiar with the original LibSVM, it should be trivial to use our implementation.
49 | In the following example, you can assume you have LibSVM's **heart\_scale** and **heart\_scale\_predict** datasets in your Android storage. Please check our [testing app](AndroidLibSVM/app/src/main/java/edu/umich/eecs/androidlibsvm/) for further reference.
50 |
51 | ### Train/Scale/Predict
52 | You can train/scale/predict just by the following three member functions declared in the LibSVM class:
53 |
54 | ```
55 | public class LibSVM {
56 | public void train(String options); // equivalent to "bash svm-train options"
57 | public void predict(String options); // equivalent to "bash svm-predict options"
58 | public void scale(String options, String fileOutPath); // equivalent to "bash svm-scale options > fileOutPath"
59 | }
60 | ```
61 |
62 | For example, if you are trying to train/scale/predict the **heart\_scale** and **heart\_scale\_predict** datasets, you can do:
63 |
64 | ```
65 | String systemPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
66 | String appFolderPath = systemPath + "libsvm/"; // your datasets folder
67 |
68 | // NOTE the space between option parameters, which is important to
69 | // keep the options consistent to the original LibSVM format
70 | svm.scale(appFolderPath + "heart_scale", appFolderPath + "heart_scale_scaled");
71 | svm.train("-t 2 "/* svm kernel */ + appFolderPath + "heart_scale_scaled " + appFolderPath + "model");
72 | svm.predict(appFolderPath + "hear_scale_predict " + appFolderPath + "model " + appFolderPath + "result");
73 | ```
74 |
75 | By reading and analyze the output file (e.g., ```appFolderPath + "result"``` in this case), most applications can easily enjoy the powerful LibSVM functionality with this project.
76 |
77 | ### Building from the source code
78 | You need Android NDK to build AndroidLibSVM. I am using the NDK-r15b and the customized(deprecated) c++ compile setting as shown in the [build.gradle](AndroidLibSVM/androidlibsvm/build.gradle).
79 | Your Android Studio might complain something about "(null)/ndk-build". This is because the compiler doesn't get the path of your local NDK path
80 | - Solution: add NDK path to your local.properties file like this:
81 | ``` ndk.dir=/Users/MyPath/Android/ndk```
82 |
83 | ### Author
84 | - This Android library is currently maintained by [Yu-Chih Tung](https://yctung.github.io/)
85 | - The core LibSVM is developed by [Chih-Jen Lin](https://www.csie.ntu.edu.tw/~cjlin/index.html) and his team
86 |
87 | ### Copyright
88 | - Feel free to use this wrapper at whatever manner you want :)
89 | - But remember to include the LibSVM's [copyright](COPYRIGHT.txt) file in your project
90 |
91 | ## Example Demo App (with a beautiful GUI)
92 | Thank Isaac Salem for building such a useful [demo app](/Example). Following shows some GUI of this demo app. Users can easily train/scale/predict their model with LibSVM through this GUI.
93 | 
94 |
95 | ### Credit
96 | [Isaac Salem](https://github.com/iamAyezak)
97 |
98 | ## Troubleshooting
99 | - If LibSVM can't read/write the expected output, check if your app has the permission of ```READ_EXTERNAL_STORAGE``` and ```WRITE_EXTERNAL_STORAGE```
100 | - If LibSVM crashes, ensure your input options follow the original LibSVM format
101 | - We don't support input as an array (or other data types) now. Please save your dataset to train/predict as files and ensure they are accessible in the Android.
102 |
--------------------------------------------------------------------------------
/Release/androidlibsvm-release.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yctung/AndroidLibSVM/282e44fa88153b4334b759af8c5632428175a26e/Release/androidlibsvm-release.aar
--------------------------------------------------------------------------------