Skip to content

Commit 4716ad6

Browse files
committed
v1.3, added support for MultiWindow and text drag-and-drop on Samsung's devices
1 parent 5eabab6 commit 4716ad6

File tree

11 files changed

+283
-13
lines changed

11 files changed

+283
-13
lines changed

Changes.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
v1.3
2+
3+
* Support for MultiWindow and drag-and-drop on Samsung's devices:
4+
drag a "file path text" label from your favorite file explorer app,
5+
using the "drag-n-drop" Samsung's MultiWindow button located in the middle multiwindow menu.
6+
Only *text labels* from other apps are supported (not objects).
7+
8+
9+
v1.2
10+
11+
* Added support for multiple file selection.
12+
13+
14+
v1.1
15+
16+
* Based on triops v7.3
17+
18+
19+
v1.0 (initial release):
20+
21+
* Based on triops v7.2.1

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
triops.apk:
22
a simple Android tool for encryption/decryption of files.
33

4-
Last version available and compiled is v1.2. Check [list of changes between versions](Changes.md).
4+
Last version available and compiled is v1.3. Check [list of changes between versions](Changes.md).
55

6-
apk available here:
6+
apk available [https://github.com/circulosmeos/triops.apk/releases/download/v1.3/triops.apk](here):
77
[http://wp.me/p2FmmK-8T](http://wp.me/p2FmmK-8T)
88

99
![](https://circulosmeos.files.wordpress.com/2015/09/triops-apk1.png)
@@ -25,6 +25,7 @@ Features:
2525
* Files bigger than 2 GiB can be managed.
2626
* Speed is extremely high: the app uses a native OS library and CHACHA20 is a very fast encryption algorithm: it is as fast as RC4.
2727
* Code for the Android file browser is a slightly modified version of ingyesid‘s [simple-file-chooser](https://github.com/ingyesid/simple-file-chooser).
28+
* Support for MultiWindow and drag-and-drop on Samsung's devices (file path text, via drag-n-drop Samsung's MultiWindow button).
2829
* Licensed as [GPL v3](http://www.gnu.org/licenses/gpl-3.0.html)
2930

3031
Known limitations:

app/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ android {
88
applicationId "com.example.triops"
99
minSdkVersion 7
1010
targetSdkVersion 22
11-
versionName '1.2'
11+
versionName '1.3'
1212
ndk {
1313
moduleName "com.example.triops"
1414
}
@@ -47,4 +47,6 @@ android {
4747
dependencies {
4848
compile 'com.android.support:support-v4:21.0.3'
4949
compile 'com.android.support:appcompat-v7:21.0.3'
50+
compile project(':multiwindow-v1.2.6')
51+
compile project(':sdk-v1.0.0')
5052
}

app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
<uses-sdk
88
android:minSdkVersion="7"
99
android:targetSdkVersion="17" />
10-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
10+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
11+
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY"/>
1112

1213
<application
1314
android:allowBackup="true"
@@ -16,6 +17,10 @@
1617
android:theme="@style/AppTheme"
1718
android:supportsRtl="true">
1819

20+
<meta-data android:name="com.samsung.android.sdk.multiwindow.enable"
21+
android:value="true" />
22+
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true"/>
23+
1924
<activity
2025
android:name=".MainActivity"
2126
android:label="@string/app_name"
@@ -24,6 +29,7 @@
2429
<action android:name="android.intent.action.MAIN" />
2530

2631
<category android:name="android.intent.category.LAUNCHER" />
32+
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
2733
</intent-filter>
2834
</activity>
2935

app/src/main/java/com/example/triops/MainActivity.java

Lines changed: 243 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,36 @@
11
package com.example.triops;
22

3+
import android.content.ClipData;
4+
import android.content.ClipDescription;
5+
import android.content.Intent;
6+
import android.graphics.Color;
37
import android.graphics.PorterDuff;
8+
import android.graphics.Rect;
9+
import android.graphics.drawable.ColorDrawable;
10+
import android.os.Bundle;
411
import android.os.Handler;
512
import android.support.v4.app.FragmentActivity;
613
import android.support.v7.app.ActionBarActivity;
7-
import android.content.Intent;
8-
import android.os.Bundle;
14+
import android.text.InputType;
915
import android.text.method.LinkMovementMethod;
16+
import android.util.Log;
17+
import android.view.DragEvent;
1018
import android.view.Menu;
1119
import android.view.MenuItem;
1220
import android.view.View;
21+
import android.view.WindowManager;
1322
import android.widget.Button;
1423
import android.widget.CheckBox;
24+
import android.widget.EditText;
25+
import android.widget.ImageView;
1526
import android.widget.ScrollView;
1627
import android.widget.TextView;
17-
import android.widget.EditText;
1828
import android.widget.Toast;
19-
import android.text.InputType;
2029

2130
import com.orleonsoft.android.simplefilechooser.Constants;
22-
import com.orleonsoft.android.simplefilechooser.FileInfo;
2331
import com.orleonsoft.android.simplefilechooser.ui.FileChooserActivity;
32+
import com.samsung.android.sdk.multiwindow.SMultiWindow;
33+
import com.samsung.android.sdk.multiwindow.SMultiWindowActivity;
2434

2535
import java.util.ArrayList;
2636
import java.util.regex.Matcher;
@@ -55,6 +65,9 @@ private enum FILE_OPERATION { OPERATION_CRYPT, OPERATION_DECRYPT }
5565
private ArrayList<String> strExternalFile = null;
5666
private String MULTIPLE_FILES_SELECTED = "Multiple files selected";
5767
private String strExternalPasswordFile;
68+
private boolean bMultiwindow=false;
69+
private SMultiWindow mMultiWindow = null;
70+
private SMultiWindowActivity mMultiWindowActivity = null;
5871

5972
/* this is used to load the 'name' library on application
6073
* startup. The library has already been unpacked into
@@ -69,8 +82,6 @@ private enum FILE_OPERATION { OPERATION_CRYPT, OPERATION_DECRYPT }
6982
//public native int triops(int argc, String[] argv);
7083
public native int triops(String[] argv);
7184

72-
final FragmentActivity activityForButton = this;
73-
7485
@Override
7586
protected void onCreate(Bundle savedInstanceState) {
7687
super.onCreate(savedInstanceState);
@@ -90,8 +101,233 @@ protected void onCreate(Bundle savedInstanceState) {
90101
// show links in tvwLog
91102
tvwLog.setMovementMethod(LinkMovementMethod.getInstance());
92103
// this will last just until next tvwLog modification ! Enough.
104+
105+
// ***************************************************************
106+
// Samsung's Multiwindow support
107+
SMultiWindow mMultiWindow = new SMultiWindow();
108+
if (mMultiWindow.getVersionCode() > 0) {
109+
// This device support MultiWindow Feature.
110+
if (mMultiWindow.isFeatureEnabled(SMultiWindow.MULTIWINDOW)) {
111+
// This device support MultiWindow.
112+
bMultiwindow=true;
113+
114+
Toast.makeText(MainActivity.this,
115+
"There is MultiWindow support!",
116+
Toast.LENGTH_LONG).show();
117+
118+
mMultiWindowActivity = new SMultiWindowActivity(this);
119+
120+
boolean success = mMultiWindowActivity
121+
.setStateChangeListener(new SMultiWindowActivity.StateChangeListener() {
122+
@Override
123+
public void onModeChanged(boolean arg0) {
124+
// TODO Auto-generated method stub
125+
/*if (arg0) {
126+
Toast.makeText(MainActivity.this,
127+
"MultiWindow Mode is changed to Multi-Window",
128+
Toast.LENGTH_LONG).show();
129+
} else {
130+
Toast.makeText(MainActivity.this,
131+
"MultiWindow Mode is changed to Normal-Window",
132+
Toast.LENGTH_LONG).show();
133+
}*/
134+
}
135+
136+
@Override
137+
public void onZoneChanged(int arg0) {
138+
// TODO Auto-generated method stub
139+
String zoneInfo = "Free zone";
140+
if (arg0 == SMultiWindowActivity.ZONE_A) {
141+
zoneInfo = "Zone A";
142+
} else if (arg0 == SMultiWindowActivity.ZONE_B) {
143+
zoneInfo = "Zone B";
144+
}
145+
/*Toast.makeText(MainActivity.this,
146+
"Activity zone info is changed to " + zoneInfo,
147+
Toast.LENGTH_LONG).show();*/
148+
}
149+
150+
@Override
151+
public void onSizeChanged(Rect arg0) {
152+
// TODO Auto-generated method stub
153+
/*Toast.makeText(MainActivity.this,
154+
"Activity size info is changed to " + arg0,
155+
Toast.LENGTH_LONG).show();*/
156+
}
157+
});
158+
159+
} // if (mMultiWindow.isFeatureEnabled(SMultiWindow.MULTIWINDOW))
160+
} // if (mMultiWindow.getVersionCode() > 0)
161+
// ***************************************************************
162+
163+
164+
// Creates a new drag event listener
165+
myDragEventListener mDragListen = new myDragEventListener();
166+
167+
// Sets the drag event listener for the View
168+
findViewById(R.id.btnChooseFile).setOnDragListener(mDragListen);
169+
170+
findViewById(R.id.btnChoosePasswordFile).setOnDragListener(mDragListen);
171+
93172
}
94173

174+
175+
protected class myDragEventListener implements View.OnDragListener {
176+
177+
int iPreviousColor = 0;
178+
179+
// This is the method that the system calls when it dispatches a drag event to the
180+
// listener.
181+
public boolean onDrag(View v, DragEvent event) {
182+
183+
CharSequence dragData;
184+
final int colorBLUE = Color.rgb( 96, 149, 237);
185+
final int colorGREEN = Color.rgb( 98, 205, 101);
186+
187+
// Defines a variable to store the action type for the incoming event
188+
final int action = event.getAction();
189+
190+
// Handles each of the expected events
191+
switch(action) {
192+
193+
case DragEvent.ACTION_DRAG_STARTED:
194+
195+
// Determines if this View can accept the dragged data
196+
if ( event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) ) {
197+
198+
// As an example of what your application might do,
199+
// applies a blue color tint to the View to indicate that it can accept
200+
// data.
201+
try {
202+
iPreviousColor = ((ColorDrawable) (v.getBackground())).getColor();
203+
} catch (Exception e) {
204+
iPreviousColor = Color.LTGRAY;
205+
}
206+
207+
v.setBackgroundColor( colorBLUE );
208+
209+
// Invalidate the view to force a redraw in the new tint
210+
v.invalidate();
211+
212+
// returns true to indicate that the View can accept the dragged data.
213+
return true;
214+
215+
}
216+
217+
// Returns false. During the current drag and drop operation, this View will
218+
// not receive events again until ACTION_DRAG_ENDED is sent.
219+
return false;
220+
221+
case DragEvent.ACTION_DRAG_ENTERED:
222+
223+
// Applies a green tint to the View. Return true; the return value is ignored.
224+
v.setBackgroundColor(colorGREEN);
225+
226+
// Invalidate the view to force a redraw in the new tint
227+
v.invalidate();
228+
229+
return true;
230+
231+
case DragEvent.ACTION_DRAG_LOCATION:
232+
233+
// Ignore the event
234+
return true;
235+
236+
case DragEvent.ACTION_DRAG_EXITED:
237+
238+
// Re-sets the color tint to blue. Returns true; the return value is ignored.
239+
v.setBackgroundColor(colorBLUE);
240+
241+
// Invalidate the view to force a redraw in the new tint
242+
v.invalidate();
243+
244+
return true;
245+
246+
case DragEvent.ACTION_DROP:
247+
248+
// Gets the item containing the dragged data
249+
ClipData.Item item = event.getClipData().getItemAt(0);
250+
251+
// Gets the text data from the item.
252+
dragData = item.getText();
253+
254+
// Displays a message containing the dragged data.
255+
/*Toast.makeText(MainActivity.this,
256+
"Dragged data is " + dragData.toString(), Toast.LENGTH_LONG).show();*/
257+
/*Toast.makeText(MainActivity.this,
258+
String.valueOf( event.getClipData().getItemCount() ), Toast.LENGTH_LONG).show();*/
259+
260+
// Turns off any color tints
261+
v.setBackgroundColor(iPreviousColor);
262+
263+
// Invalidates the view to force a redraw
264+
v.invalidate();
265+
266+
// action to perform:
267+
if ( dragData != null &&
268+
dragData.toString().matches("^/.+[^/]$") ) {
269+
270+
// check that there're no multiple lines in dragged text!
271+
// TODO: accept drag-n-drop texts with multiple file paths
272+
Pattern regex = Pattern.compile("^.+\\n.+", Pattern.DOTALL);
273+
Matcher regexMatcher = regex.matcher(dragData.toString());
274+
if (regexMatcher.find()) {
275+
Toast.makeText(MainActivity.this, "text dropped is not a valid file path!",
276+
Toast.LENGTH_LONG).show();
277+
} else {
278+
279+
Intent data = new Intent(MainActivity.this, MainActivity.class);
280+
ArrayList<String> list_of_selected_files = new ArrayList<String>();
281+
list_of_selected_files.add(dragData.toString());
282+
data.putStringArrayListExtra(Constants.KEY_FILE_SELECTED,
283+
list_of_selected_files);
284+
onActivityResult(
285+
(v.getId() == R.id.btnChooseFile) ?
286+
REQUEST_CODE_GET_FILE_TO_OVERWRITE :
287+
REQUEST_CODE_GET_PASSWORD_FILE,
288+
RESULT_OK, data);
289+
}
290+
291+
} else {
292+
Toast.makeText(MainActivity.this, "text dropped is not a valid file path",
293+
Toast.LENGTH_LONG).show();
294+
}
295+
296+
297+
// Returns true. DragEvent.getResult() will return true.
298+
return true;
299+
300+
case DragEvent.ACTION_DRAG_ENDED:
301+
302+
// Turns off any color tinting
303+
v.setBackgroundColor(iPreviousColor);
304+
305+
// Invalidates the view to force a redraw
306+
v.invalidate();
307+
308+
// Does a getResult(), and displays what happened.
309+
if (event.getResult()) {
310+
//Toast.makeText(MainActivity.this, "The drop was handled.", Toast.LENGTH_LONG).show();
311+
312+
} else {
313+
Toast.makeText(MainActivity.this, "The drop didn't work.", Toast.LENGTH_LONG).show();
314+
315+
}
316+
317+
// returns true; the value is ignored.
318+
return true;
319+
320+
// An unknown action type was received.
321+
default:
322+
Log.e("DragDrop Example", "Unknown action type received by OnDragListener.");
323+
break;
324+
}
325+
326+
return false;
327+
}
328+
};
329+
330+
95331
@Override
96332
public boolean onCreateOptionsMenu(Menu menu) {
97333
getMenuInflater().inflate(R.menu.main, menu);

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<string name="filebrowser_name">File Browser</string>
1414
<string name="password">Password:</string>
1515
<string name="password_hint">password...</string>
16-
<string name="initiallogtext">triops (v7.3) port to Android, version 1.2 (2015&#8211;10)\n <a href ="https://wp.me/p2FmmK-8T">circulosmeos.wordpress.com</a>\n <a href="https://github.com/circulosmeos/triops.apk">github.com/circulosmeos/triops.apk</a>\nlicensed under GNU General Public License <a href="http://www.gnu.org/licenses/gpl-3.0.en.html">(GPL) v3</a>.\n\nEncrypt and decrypt files \n with <a href="https://en.wikipedia.org/wiki/Salsa20#ChaCha20_adoption">CHACHA20</a>+<a href="https://en.wikipedia.org/wiki/SHA-3#History">KECCAK</a>.\nOperation will be automagically inferred from file extension.\n\n</string>
16+
<string name="initiallogtext">triops (v7.3) port to Android, version 1.3 (2015&#8211;12)\n <a href ="https://wp.me/p2FmmK-8T">circulosmeos.wordpress.com</a>\n <a href="https://github.com/circulosmeos/triops.apk">github.com/circulosmeos/triops.apk</a>\nlicensed under GNU General Public License <a href="http://www.gnu.org/licenses/gpl-3.0.en.html">(GPL) v3</a>.\n\nEncrypt and decrypt files \n with <a href="https://en.wikipedia.org/wiki/Salsa20#ChaCha20_adoption">CHACHA20</a>+<a href="https://en.wikipedia.org/wiki/SHA-3#History">KECCAK</a>.\nOperation will be automagically inferred from file extension.\n\n</string>
1717

1818
<string name="fileSize">File Size</string>
1919
<string name="currentDir">Current Dir</string>

multiwindow-v1.2.6/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
configurations.create("default")
2+
artifacts.add("default", file('multiwindow-v1.2.6.jar'))
16.9 KB
Binary file not shown.

sdk-v1.0.0/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
configurations.create("default")
2+
artifacts.add("default", file('sdk-v1.0.0.jar'))

sdk-v1.0.0/sdk-v1.0.0.jar

1.96 KB
Binary file not shown.

0 commit comments

Comments
 (0)