Merge pull request #211 from hyb1996/new_ui

release 2.0.14 Beta
This commit is contained in:
Stardust
2017-07-12 14:05:22 +08:00
committed by GitHub
48 changed files with 800 additions and 150 deletions

View File

@@ -9,8 +9,8 @@ android {
applicationId "com.stardust.scriptdroid"
minSdkVersion 17
targetSdkVersion 23
versionCode 145
versionName "2.0.13 Beta3"
versionCode 146
versionName "2.0.14 Beta"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
ndk {

View File

@@ -80,6 +80,11 @@
<activity android:name=".ui.help.LocalWebViewActivity"/>
<activity android:name=".external.tasker.TaskerScriptEditActivity_"/>
<activity android:name=".ui.edit.ViewSampleActivity"/>
<activity android:name=".external.widget.ScriptWidgetSettingsActivity_">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
<activity
android:name="com.stardust.autojs.runtime.api.image.ScreenCaptureRequestActivity"
android:taskAffinity="com.stardust.autojs.runtime.api.image.ScreenCaptureRequestActivity"
@@ -241,6 +246,15 @@
</intent-filter>
</activity>
<receiver android:name=".external.widget.ScriptWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/script_widget_config"/>
</receiver>
<!-- 声明广告SDK所需要的组件 -->
<service
android:name="com.qq.e.comm.DownloadService"

View File

@@ -1,3 +0,0 @@
module.exports = function(){
}

View File

@@ -0,0 +1,66 @@
"auto";
var 好友验证信息 = "AutoJs自动添加群好友";
var 延迟 = 500;
toast("请打开群成员列表");
var added = {};
while(true){
var list = className("AbsListView").findOne();
list.children().each(function(child){
if(child.className() != "android.widget.FrameLayout"){
return;
}
if(!isGroupMember(child)){
return;
}
if(isMyself(child)){
return;
}
child.child(0).click();
sleep(500);
addAsFriend();
sleep(延迟);
});
className("AbsListView").findOne().scrollForward();
}
function isGroupMember(child){
if(child.childCount() != 1){
return false;
}
return child.child(0) && child.child(0).className() == "android.widget.FrameLayout";
}
function isMyself(child){
var l = child.findByText("我");
return l && l.size() > 0;
}
function addAsFriend(){
var qq = getQQ();
if(added[qq]){
while(!click("返回"));
return;
}
added[qq] = true;
if(click("加好友")){
sleep(800);
setText(0, 好友验证信息);
while(!click("发送"));
sleep(800);
if(click("取消")){
sleep(400);
}
back();
}else{
back();
}
}
function getQQ(){
var qq = textMatches("\\d{5,12}").findOne().text();
return qq;
}

View File

@@ -5,21 +5,29 @@ function 下滑(){
}
function (){
className("ImageView").desc("赞").click();
var like = className("ImageView").desc("赞").find();
if(like){
like.click();
return true;
}
return false;
}
function 显示更多(){
for(let i = 0; i < 2;i++){
click("显示更多");
}
}
}
toast("请打开自己的资料页,点击点赞图标");
sleep(100);
waitForActivity("com.tencent.mobileqq.activity.VisitorsActivity");
while(notStopped()){
for(let i = 0; i < 10; i++){
();
var i = 0;
while(i < 10){
i += () ? 1 : 0;
click("取消");
}
显示更多();
下滑();

View File

@@ -1,49 +0,0 @@
"auto";
var 延迟 = 0;
function 点赞(){
className("AbsListView").findOne()
.children().each(function(ss){
try{
var 一行 = 找到图标那一行(ss);
if(一行){
一行.child(1).click();
if(延迟 > 0){
sleep(延迟);
}
}
}catch(e){}
});
}
function 找到图标那一行(s){
for(let i = 0; i < s.getChildCount(); i++){
var child = s.child(i);
if(child && child.className()
.endsWith("RelativeLayout") &&
child.getChildCount() >= 4){
if(是图片(child.child(1)) &&
是图片(child.child(2)) &&
是图片(child.child(3))){
return child;
}
}
}
}
function 是图片(item){
return item &&
item.className().endsWith("ImageView");
}
function 下滑(){
className("AbsListView").findOne()
.scrollForward();
}
while(true){
点赞();
下滑();
}

View File

@@ -0,0 +1,71 @@
"auto";
var 延迟 = 0;
if(!requestScreenCapture()){
toast("请求截图失败");
stop();
}
var capture;
function like(){
capture = captureScreen();
className("AbsListView").findOne()
.children().each(function(ss){
try{
var iconLine = findIconLine(ss);
if(iconLine){
var likeIcon = iconLine.child(1).child(0);
if(notLiked(likeIcon)){
likeIcon.click();
}
if(延迟 > 0){
sleep(延迟);
}
}
}catch(e){
log(e);
}
});
}
function findIconLine(s){
for(let i = 0; i < s.getChildCount(); i++){
var child = s.child(i);
if(child && child.className()
.endsWith("RelativeLayout") &&
child.getChildCount() >= 4){
if(isImage(child.child(1)) &&
isImage(child.child(2)) &&
isImage(child.child(3))){
return child;
}
}
}
}
function isImage(item){
if(!item){
return false;
}
if(item.className().endsWith("ImageView")){
return true;
}
if(item.childCount() == 1){
return isImage(item.child(0));
}
return false;
}
function notLiked(likeIcon){
var x = likeIcon.bounds().centerX();
var y = likeIcon.bounds().centerY();
return images.detectsColor(capture, x, y, 0x767886);
}
toast("请打开QQ空间并慢慢下滑");
while(true){
like();
}

View File

@@ -1,5 +1,6 @@
"auto";
//漏赞过多请稍微调大延迟
var 延迟 = 200;

View File

@@ -1,10 +1,11 @@
"auto";
toast("请打开一个聊天窗口");
sleep(500);
while(true){
input("我喜欢你");
setText("我喜欢你");
click("发送");
sleep(200);
}

View File

@@ -3,8 +3,8 @@
launchApp("网易云音乐");
toast("打开一个歌曲的评论页面");
//循环直至当前为评论页面
waitActivity("com.netease.cloudmusic.activity.ResourceCommentActivity");
//等待当前为评论页面
waitForActivity("com.netease.cloudmusic.activity.ResourceCommentActivity");
while(true){

View File

@@ -0,0 +1,12 @@
if(!requestScreenCapture()){
toast("请求截图失败");
}
sleep(2000);
var x = 760;
var y = 180;
//获取在点(x, y)处的颜色
var c = images.pixel(captureScreen(), x, y);
//显示该颜色
toast((c >>> 0).toString(16));
//检测在点(x, y)处是否有颜色0x73bdb6 (模糊比较)
toast(images.detectsColor(captureScreen(), x, y, 0x73bdb6))

View File

@@ -83,10 +83,6 @@ public class App extends MultiDexApplication {
}
public static String getResString(int id) {
return getApp().getString(id);
}
public VolumeChangeObserver getVolumeChangeObserver() {
return mVolumeChangeObserver;
}

View File

@@ -8,15 +8,13 @@ import com.stardust.autojs.runtime.api.AutomatorConfig;
import com.stardust.automator.AccessibilityEventCommandHost;
import com.stardust.scriptdroid.autojs.AutoJs;
import org.mozilla.javascript.tools.debugger.Dim;
import org.mozilla.javascript.tools.debugger.GuiCallback;
import java.util.concurrent.TimeUnit;
/**
* Created by Stardust on 2017/1/31.
*/
public class Pref {
private static final boolean enableRemoveAdOption = true;
private static final SharedPreferences DISPOSABLE_BOOLEAN = App.getApp().getSharedPreferences("DISPOSABLE_BOOLEAN", Context.MODE_PRIVATE);
private static final String KEY_SERVER_ADDRESS = "Still love you...17.5.14";
@@ -99,7 +97,7 @@ public class Pref {
}
private static String getString(int id) {
return App.getResString(id);
return App.getApp().getString(id);
}
public static int getMaxTextLengthForCodeCompletion() {
@@ -147,6 +145,9 @@ public class Pref {
def().edit().putLong(KEY_LAST_SHOW_AD_MILLIS, System.currentTimeMillis()).apply();
return true;
case "Off":
if (enableRemoveAdOption) {
return false;
}
lastShowMillis = def().getLong(KEY_LAST_SHOW_AD_MILLIS, 0);
if (System.currentTimeMillis() - lastShowMillis < TimeUnit.DAYS.toMillis(2)) {
return false;

View File

@@ -51,15 +51,17 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
@BindView(R.id.text_start_or_pause)
TextView mStartOrPauseRecordText;
@BindView(R.id.stop_record)
View mStopRecord;
@BindView(R.id.discard_record)
View mDiscardRecord;
private Recorder mRecorder;
private Context mContext;
private boolean mDiscard = false;
private KeyObserver mKeyObserver;
private VolumeChangeObserver.OnVolumeChangeListener mOnVolumeChangeListener = new VolumeChangeObserver.OnVolumeChangeListener() {
@Override
public void onVolumeChange() {
@@ -123,6 +125,12 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
}
}
@OnClick(R.id.discard_record)
void discardRecord() {
mDiscard = true;
stopRecord();
}
private void resumeRecord() {
mRecorder.resume();
setState(Recorder.STATE_RECORDING);
@@ -135,6 +143,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
}
private void startRecord() {
mDiscard = false;
mRecorder = mRecordedByRootSwitch.isChecked() ? new TouchRecorder(mContext) : AutoJs.getInstance().getAccessibilityActionRecorder();
mRecorder.setOnStateChangedListener(this);
mRecorder.start();
@@ -144,6 +153,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
private void setState(int state) {
mStopRecord.setVisibility(state == Recorder.STATE_STOPPED ? View.GONE : View.VISIBLE);
mDiscardRecord.setVisibility(state == Recorder.STATE_STOPPED ? View.GONE : View.VISIBLE);
mStartOrPauseRecordIcon.setImageResource(state == Recorder.STATE_RECORDING ? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_48dp);
//我知道这样写代码会被打 但我懒...
mStartOrPauseRecordText.setText(state == Recorder.STATE_RECORDING ? R.string.text_pause_record :
@@ -191,7 +201,9 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
@Override
public void onStop() {
MainActivity.onRecordStop(mContext, mRecorder.getCode());
if (!mDiscard) {
MainActivity.onRecordStop(mContext, mRecorder.getCode());
}
mRecorder = null;
}

View File

@@ -27,8 +27,8 @@ public class LayoutInspector {
mCapture = null;
} else {
final AccessibilityNodeInfo root = service.getRootInActiveWindow();
Log.d(LOG_TAG, "captureCurrentWindow: root = null");
if (root == null) {
Log.d(LOG_TAG, "captureCurrentWindow: root = null");
mCapture = null;
} else {
mExecutor.execute(new Runnable() {

View File

@@ -1,6 +1,7 @@
package com.stardust.scriptdroid.external.open;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
@@ -10,6 +11,8 @@ import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.main.MainActivity;
import com.stardust.scriptdroid.R;
import java.io.FileNotFoundException;
/**
* Created by Stardust on 2017/2/2.
*/
@@ -30,13 +33,25 @@ public class ImportIntentActivity extends BaseActivity {
@Override
protected void onNewIntent(Intent intent) {
handleIntent(intent);
try {
handleIntent(intent);
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(this, R.string.edit_and_run_handle_intent_error, Toast.LENGTH_LONG).show();
finish();
}
}
private void handleIntent(Intent intent) {
final String path = intent.getData().getPath();
if (!TextUtils.isEmpty(path))
MainActivity.importScriptFile(this, path);
private void handleIntent(Intent intent) throws FileNotFoundException {
Uri uri = intent.getData();
if (uri != null && "content".equals(uri.getScheme())) {
MainActivity.importScriptFileByInputStream(this, getContentResolver().openInputStream(uri));
} else {
final String path = intent.getData().getPath();
if (!TextUtils.isEmpty(path)) {
MainActivity.importScriptFile(this, path);
}
}
finish();
}

View File

@@ -0,0 +1,58 @@
package com.stardust.scriptdroid.external.widget;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;
import com.stardust.pio.PFile;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.external.open.RunIntentActivity;
import java.util.HashSet;
import java.util.Set;
/**
* Created by Stardust on 2017/7/11.
*/
public class ScriptWidget extends AppWidgetProvider {
private static final String LOG_TAG = "ScriptWidget";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
Set<Integer> appWidgetIdSet = new HashSet<>();
for (int appWidgetId : appWidgetIds) {
updateWidget(context, appWidgetId, ScriptWidgets.getPathForAppWidgetId(appWidgetId));
appWidgetIdSet.add(appWidgetId);
}
if (appWidgetIdSet.size() > 1)
ScriptWidgets.removeAllNotIn(appWidgetIdSet);
}
static boolean updateWidget(Context context, int widgetId, String path) {
if (TextUtils.isEmpty(path) || widgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
return false;
}
String name = PFile.getNameWithoutExtension(path);
int requestCode = ScriptWidgets.getRequestCodeForAppWidgetId(widgetId);
Log.d(LOG_TAG, "updateWidget: id = " + widgetId + ", requestCode = " + requestCode + ", path = " + path);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_script_shortcut);
views.setOnClickPendingIntent(R.id.widget, PendingIntent.getActivity(context, requestCode,
new Intent(context, RunIntentActivity.class)
.putExtra(CommonUtils.EXTRA_KEY_PATH, path)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_UPDATE_CURRENT));
views.setTextViewText(R.id.name, name);
appWidgetManager.updateAppWidget(widgetId, views);
ScriptWidgets.setPathForAppWidgetId(widgetId, path);
return true;
}
}

View File

@@ -0,0 +1,100 @@
package com.stardust.scriptdroid.external.widget;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.external.open.RunIntentActivity;
import com.stardust.scriptdroid.external.tasker.TaskerScriptEditActivity;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
/**
* Created by Stardust on 2017/7/11.
*/
@EActivity(R.layout.activity_script_widget_settings)
public class ScriptWidgetSettingsActivity extends BaseActivity {
private String mSelectedScriptFilePath;
private StorageScriptProvider mStorageScriptProvider;
private int mAppWidgetId;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAppWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
@AfterViews
void setUpViews() {
BaseActivity.setToolbarAsBack(this, R.id.toolbar, getString(R.string.text_please_choose_a_script));
initScriptListRecyclerView();
}
private void initScriptListRecyclerView() {
mStorageScriptProvider = StorageScriptProvider.getExternalStorageProvider();
ScriptListWithProgressBarView scriptList = (ScriptListWithProgressBarView) findViewById(R.id.script_list);
scriptList.setScriptFileOperationEnabled(false);
scriptList.setStorageScriptProvider(mStorageScriptProvider);
scriptList.setCurrentDirectory(StorageScriptProvider.DEFAULT_DIRECTORY);
scriptList.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
@Override
public void onClick(ScriptFile file, int position) {
mSelectedScriptFilePath = file.getPath();
finish();
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_refresh) {
mStorageScriptProvider.refreshAll();
} else if (item.getItemId() == R.id.action_clear_file_selection) {
mSelectedScriptFilePath = null;
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.script_widget_settings_menu, menu);
return true;
}
@Override
public void finish() {
if (ScriptWidget.updateWidget(this, mAppWidgetId, mSelectedScriptFilePath)) {
setResult(RESULT_OK, new Intent()
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId));
} else {
setResult(RESULT_CANCELED, new Intent()
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId));
}
super.finish();
}
}

View File

@@ -0,0 +1,72 @@
package com.stardust.scriptdroid.external.widget;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import com.stardust.scriptdroid.App;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Stardust on 2017/7/11.
*/
public class ScriptWidgets {
private static final String LOG_TAG = "ScriptWidgets";
private static SharedPreferences widgets = App.getApp().getSharedPreferences("ScriptWidgets", Context.MODE_PRIVATE);
private static final Pattern ID_PATTERN = Pattern.compile("[a-zA-Z]+_([0-9])+");
static String getPathForAppWidgetId(int id) {
return widgets.getString("path_" + id, null);
}
static void setPathForAppWidgetId(int id, String path) {
widgets.edit().putString("path_" + id, path).apply();
}
static int getRequestCodeForAppWidgetId(int id) {
int requestCode = widgets.getInt("rc_" + id, -1);
if (requestCode == -1) {
requestCode = widgets.getInt("max_rc", 0) + 1;
widgets.edit()
.putInt("rc_" + id, requestCode)
.putInt("max_rc", requestCode)
.apply();
}
return requestCode;
}
static void removeAllNotIn(Set<Integer> appWidgetIdSet) {
List<String> keysToRemove = new LinkedList<>();
for (Map.Entry<String, ?> entry : widgets.getAll().entrySet()) {
if (entry.getKey().equals("max_rc")) {
continue;
}
Matcher matcher = ID_PATTERN.matcher(entry.getKey());
if (matcher.find()) {
int id = Integer.parseInt(matcher.group(1));
if (!appWidgetIdSet.contains(id)) {
keysToRemove.add(entry.getKey());
}
} else {
Log.w(LOG_TAG, "illegal key: " + entry.getKey());
keysToRemove.add(entry.getKey());
}
}
SharedPreferences.Editor editor = widgets.edit();
for (String key : keysToRemove) {
editor.remove(key);
Log.v(LOG_TAG, "remove key: " + key);
}
editor.apply();
}
}

View File

@@ -2,6 +2,8 @@ package com.stardust.scriptdroid.ui;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
@@ -26,7 +28,9 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
public abstract class BaseActivity extends AppCompatActivity {
protected static final int PERMISSION_REQUEST_CODE = 11186;
private static boolean isRequestingPermissions = false;
private BackPressedHandler.Observer mBackPressObserver = new BackPressedHandler.Observer();
@Override
@@ -62,9 +66,14 @@ public abstract class BaseActivity extends AppCompatActivity {
protected void checkPermission(String... permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (isRequestingPermissions) {
return;
}
String[] requestPermissions = getRequestPermissions(permissions);
if (requestPermissions.length > 0)
if (requestPermissions.length > 0) {
isRequestingPermissions = true;
requestPermissions(requestPermissions, PERMISSION_REQUEST_CODE);
}
} else {
int[] grantResults = new int[permissions.length];
Arrays.fill(grantResults, PERMISSION_GRANTED);
@@ -72,6 +81,7 @@ public abstract class BaseActivity extends AppCompatActivity {
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private String[] getRequestPermissions(String[] permissions) {
List<String> list = new ArrayList<>();
@@ -112,4 +122,11 @@ public abstract class BaseActivity extends AppCompatActivity {
activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
@CallSuper
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
isRequestingPermissions = false;
}
}

View File

@@ -36,10 +36,12 @@ import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.external.floatingwindow.HoverMenuManger;
import com.stardust.scriptdroid.external.open.ImportIntentActivity;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.sample.Sample;
import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment_;
import com.stardust.util.IntentExtras;
import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.tool.DrawableSaver;
@@ -66,6 +68,7 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.io.IOException;
import java.io.InputStream;
@EActivity(R.layout.activity_main)
public class MainActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost {
@@ -81,6 +84,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
private static final String ARGUMENT_PATH = "ARGUMENT_PATH";
private static final String ACTION_IMPORT_SAMPLE = "I cannot find the way back to you...Eating...17.4.29";
private static final String ARGUMENT_SAMPLE = "Take a chance on me...ok...?";
private static final String ARGUMENT_INPUT_STREAM = "17.7.12, Hi...could we start all over again...";
@ViewById(R.id.drawer_layout)
@@ -306,7 +310,10 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
return;
switch (action) {
case ACTION_ON_ACTION_RECORD_STOPPED:
handleRecordedScript(intent.getStringExtra(ARGUMENT_SCRIPT));
IntentExtras extras = IntentExtras.fromIntent(intent);
String script = extras.get(ARGUMENT_SCRIPT);
extras.clear();
handleRecordedScript(script);
break;
case ACTION_IMPORT_SCRIPT:
handleImportScriptFile(intent);
@@ -323,10 +330,17 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
if (fragment == null) {
mIntentToHandle = intent;
} else {
fragment.importFile(intent.getStringExtra(ARGUMENT_PATH));
String path = intent.getStringExtra(ARGUMENT_PATH);
if (path != null) {
fragment.importFile(intent.getStringExtra(ARGUMENT_PATH));
return;
}
InputStream inputStream = IntentExtras.fromIntent(intent).getAndClear(ARGUMENT_INPUT_STREAM);
fragment.importFile("", inputStream);
}
}
private void handleImportSample(Intent intent) {
mViewPager.setCurrentItem(0, true);
MyScriptListFragment fragment = getMyScriptListFragment();
@@ -388,6 +402,16 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
.putExtra(ARGUMENT_PATH, path));
}
public static void importScriptFileByInputStream(Context context, InputStream inputStream) {
Intent intent = new Intent(context, MainActivity_.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP)
.putExtra(EXTRA_ACTION, ACTION_IMPORT_SCRIPT);
IntentExtras.newExtras()
.put(ARGUMENT_INPUT_STREAM, inputStream)
.putInIntent(intent);
context.startActivity(intent);
}
public static void importSample(Context context, Sample sample) {
context.startActivity(new Intent(context, MainActivity_.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP)
@@ -442,6 +466,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
StorageScriptProvider.getDefault().notifyStoragePermissionGranted();
}
@@ -456,8 +481,10 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
public static void onRecordStop(Context context, String script) {
Intent intent = new Intent(context, MainActivity_.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_ACTION, ACTION_ON_ACTION_RECORD_STOPPED)
.putExtra(ARGUMENT_SCRIPT, script);
.putExtra(EXTRA_ACTION, ACTION_ON_ACTION_RECORD_STOPPED);
IntentExtras.newExtras()
.put(ARGUMENT_SCRIPT, script)
.putInIntent(intent);
context.startActivity(intent);
}
@@ -466,4 +493,6 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
public OnActivityResultDelegate.Mediator getOnActivityResultDelegateMediator() {
return mActivityResultMediator;
}
}

View File

@@ -78,7 +78,6 @@ public class SplashActivity extends BaseActivity {
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:clipToPadding="false"
android:theme="@style/AppTheme.AppBarOverlay">
<com.stardust.theme.widget.ThemeColorToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:title="@string/_app_name">
</com.stardust.theme.widget.ThemeColorToolbar>
</android.support.design.widget.AppBarLayout>
<com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView
android:id="@+id/script_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fafafa"/>
</LinearLayout>

View File

@@ -148,6 +148,37 @@
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#c4c4c4"/>
<LinearLayout
android:id="@+id/discard_record"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingTop="16dp"
android:visibility="gone">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="8dp"
android:src="@drawable/ic_close_white_24dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_discard_record"
android:textColor="@android:color/primary_text_dark"
android:textSize="16sp"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/icon"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:src="@drawable/ic_node_js_black"/>
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center"
android:maxLines="1"
android:textColor="@android:color/white"
android:textSize="12sp"/>
</LinearLayout>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_refresh"
android:icon="@drawable/ic_refresh_white_24dp"
android:orderInCategory="100"
android:title="@string/text_refresh"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_clear_file_selection"
android:orderInCategory="200"
android:title="@string/text_clear_file_selection"
app:showAsAction="never"/>
</menu>

View File

@@ -206,6 +206,7 @@
<string name="hint_loop_delay">延迟多少秒后开始循环</string>
<string name="text_number_format_error">格式错误</string>
<string name="text_accessibility_settings">打开无障碍服务</string>
<string name="text_discard_record">放弃录制</string>
<string-array name="record_control_keys">
<item></item>
@@ -224,7 +225,7 @@
<string-array name="ad_showing_mode_keys">
<item>默认</item>
<item>每天显示一次</item>
<item>两天显示一次</item>
<item>关闭广告</item>
</string-array>
<string-array name="ad_showing_mode_values">

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:configure="com.stardust.scriptdroid.external.widget.ScriptWidgetSettingsActivity_"
android:initialLayout="@layout/widget_script_shortcut"
android:minHeight="40dp"
android:minWidth="40dp"
android:previewImage="@drawable/ic_node_js_black"
android:resizeMode="none"/>

View File

@@ -6,6 +6,7 @@
<application
>
<activity android:name=".execution.ScriptExecuteActivity"/>
<service
android:name="com.stardust.view.accessibility.AccessibilityService"
android:label="@string/_app_name"
@@ -18,6 +19,7 @@
android:resource="@xml/accessibility_service_config"/>
</service>
</application>
</manifest>

View File

@@ -88,7 +88,7 @@ module.exports = function(__runtime__, scope){
}, arguments);
}
automator.input = function(a, b){
automator.setText = function(a, b){
if(arguments.length == 1){
return __runtime__.automator.setText(__runtime__.automator.editable(-1), a);
}else{
@@ -96,8 +96,16 @@ module.exports = function(__runtime__, scope){
}
}
automator.input = function(a, b){
if(arguments.length == 1){
return __runtime__.automator.appendText(__runtime__.automator.editable(-1), a);
}else{
return __runtime__.automator.appendText(__runtime__.automator.editable(a), b);
}
}
scope.__asGlobal__(__runtime__.automator, ['back', 'home', 'powerDialog', 'notifications', 'quickSettings', 'recents', 'splitScreen']);
scope.__asGlobal__(automator, ['click', 'longClick', 'press', 'swipe', 'gesture', 'gestures', 'gestureAsync', 'gesturesAsync', 'scrollDown', 'scrollUp', 'input']);
scope.__asGlobal__(automator, ['click', 'longClick', 'press', 'swipe', 'gesture', 'gestures', 'gestureAsync', 'gesturesAsync', 'scrollDown', 'scrollUp', 'input', 'setText']);
return automator;
}

View File

@@ -41,7 +41,7 @@ module.exports = function(__runtime__, scope){
return __runtime__.info.getLatestActivity();
}
scope.waitActivity = function(activity, delay){
scope.waitForActivity = function(activity, delay){
delay = delay || 200;
while(scope.currentActivity() != activity){
sleep(delay);

View File

@@ -1,18 +1,23 @@
module.exports = function(__runtime__, scope){
var images = {};
if(android.os.Build.VERSION.SDK_INT < 19){
return images;
}
var colorFinder = __runtime__.images.colorFinder;
var rtImages = __runtime__.getImages();
images.requestScreenCapture = __runtime__.images.requestScreenCapture.bind(__runtime__.images);
var colorFinder = rtImages.colorFinder;
images.captureScreen = __runtime__.images.captureScreen.bind(__runtime__.images);
images.requestScreenCapture = rtImages.requestScreenCapture.bind(rtImages);
images.saveImage = __runtime__.images.saveImage.bind(__runtime__.images);
images.captureScreen = rtImages.captureScreen.bind(rtImages);
images.pixel = __runtime__.images.pixel;
images.saveImage = rtImages.saveImage.bind(rtImages);
images.detectsColor = __runtime__.images.detectsColor.bind(__runtime__.images);
images.pixel = rtImages.pixel;
images.detectsColor = rtImages.detectsColor.bind(rtImages);
images.findColor = function(img, color, options){
if(typeof(color) == 'string'){

View File

@@ -1,6 +1,7 @@
package com.stardust.autojs.runtime;
import android.content.Context;
import android.os.Build;
import android.support.annotation.CallSuper;
import com.stardust.autojs.engine.ScriptEngine;
@@ -40,12 +41,12 @@ public abstract class AbstractScriptRuntime {
@ScriptVariable
public UI ui;
@ScriptVariable
public Images images;
@ScriptVariable
public Dialogs dialogs;
private Images images;
private static WeakReference<Context> applicationContext;
public AbstractScriptRuntime(UiHandler uiHandler, Console console, AccessibilityBridge bridge, AppUtils appUtils, ScreenCaptureRequester screenCaptureRequester) {
@@ -54,7 +55,9 @@ public abstract class AbstractScriptRuntime {
this.automator = new SimpleActionAutomator(bridge, this);
this.info = bridge.getInfoProvider();
this.ui = new UI(uiHandler.getContext());
images = new Images(uiHandler.getContext(), this, screenCaptureRequester);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
images = new Images(uiHandler.getContext(), this, screenCaptureRequester);
}
dialogs = new Dialogs(app, uiHandler);
}
@@ -109,6 +112,12 @@ public abstract class AbstractScriptRuntime {
@CallSuper
public void onStop() {
images.releaseScreenCapturer();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
images.releaseScreenCapturer();
}
}
public Object getImages() {
return images;
}
}

View File

@@ -3,6 +3,8 @@ package com.stardust.autojs.runtime.api.image;
import android.graphics.Point;
import android.graphics.Rect;
import android.media.Image;
import android.os.Build;
import android.support.annotation.RequiresApi;
import com.stardust.autojs.runtime.ScriptInterruptedException;
import com.stardust.concurrent.VolatileBox;
@@ -18,6 +20,7 @@ import java.util.concurrent.TimeUnit;
* Created by Stardust on 2017/5/18.
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public class ColorFinder {
private static ThreadPoolExecutor sThreadPoolExecutor = new ThreadPoolExecutor(4, 16, 5, TimeUnit.MINUTES, new SynchronousQueue<Runnable>());

View File

@@ -10,6 +10,7 @@ import android.graphics.Matrix;
import android.media.Image;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Log;
import com.stardust.autojs.runtime.AbstractScriptRuntime;
import com.stardust.autojs.runtime.ScriptInterruptedException;
@@ -21,6 +22,7 @@ import com.stardust.util.ScreenMetrics;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.util.Locale;
/**
* Created by Stardust on 2017/5/20.
@@ -103,13 +105,20 @@ public class Images {
}
public static int pixel(Image image, int x, int y) {
int originX = x;
int originY = y;
x = ScreenMetrics.rescaleX(x, image.getWidth());
y = ScreenMetrics.rescaleY(y, image.getHeight());
Image.Plane plane = image.getPlanes()[0];
int offset = y * plane.getRowStride() + x * plane.getPixelStride();
int c = plane.getBuffer().getInt(offset);
Log.d("Images", String.format(Locale.getDefault(), "(%d, %d)→(%d, %d)", originX, originY, x, y));
return (c & 0xff000000) + ((c & 0xff) << 16) + (c & 0x00ff00) + ((c & 0xff0000) >> 16);
}
public static int pixel(Bitmap bitmap, int x, int y) {
x = ScreenMetrics.rescaleX(x, bitmap.getWidth());
y = ScreenMetrics.rescaleY(y, bitmap.getHeight());
return bitmap.getPixel(x, y);
}

View File

@@ -10,6 +10,7 @@ import android.widget.TextView;
import com.stardust.enhancedfloaty.FloatyService;
import com.stardust.enhancedfloaty.ResizableExpandableFloaty;
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;
import com.stardust.util.ScreenMetrics;
import com.stardust.util.ViewUtil;
import com.stardust.autojs.R;
@@ -30,6 +31,7 @@ public class ConsoleFloaty extends ResizableExpandableFloaty.AbstractResizableEx
setShouldRequestFocusWhenExpand(false);
setInitialX(100);
setInitialY(1000);
setCollapsedViewUnpressedAlpha(1.0f);
}
@Override
@@ -58,7 +60,7 @@ public class ConsoleFloaty extends ResizableExpandableFloaty.AbstractResizableEx
view.post(new Runnable() {
@Override
public void run() {
ViewUtil.setViewMeasure(view, 800, 800);
ViewUtil.setViewMeasure(view, ScreenMetrics.getDeviceScreenWidth() * 2 / 3, ScreenMetrics.getDeviceScreenHeight() / 3);
}
});
}

View File

@@ -124,6 +124,12 @@ public class StardustConsole extends AbstractConsole {
@Override
public void show() {
if (!SettingsCompat.canDrawOverlays(mUiHandler.getContext())) {
mUiHandler.post(new Runnable() {
@Override
public void run() {
}
});
SettingsCompat.manageDrawOverlays(mUiHandler.getContext());
mUiHandler.toast(R.string.text_no_floating_window_permission);
}

View File

@@ -109,12 +109,20 @@ public class SimpleActionAutomator {
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SELECT));
}
@ScriptInterface
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public boolean setText(ActionTarget target, String text) {
mScriptRuntime.requiresApi(Build.VERSION_CODES.LOLLIPOP);
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SET_TEXT, text));
}
@ScriptInterface
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public boolean appendText(ActionTarget target, String text) {
mScriptRuntime.requiresApi(Build.VERSION_CODES.LOLLIPOP);
return performAction(target.createAction(UiObject.ACTION_APPEND_TEXT, text));
}
@ScriptInterface
public boolean back() {
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);

View File

@@ -1,13 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:orientation="vertical">
<ImageView
android:layout_width="46dp"
android:layout_height="46dp"
android:padding="5dp"
android:src="@drawable/ic_debug_console"/>
</LinearLayout>

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityEventTypes="typeNotificationStateChanged|typeAnnouncement|typeAssistReadingContext|typeContextClicked|typeGestureDetectionEnd|typeGestureDetectionStart|typeTouchExplorationGestureEnd|typeTouchExplorationGestureStart|typeTouchInteractionEnd|typeTouchInteractionStart|typeViewAccessibilityFocusCleared|typeViewAccessibilityFocused|typeViewClicked|typeViewHoverEnter|typeViewHoverExit|typeViewFocused|typeViewLongClicked|typeViewScrolled|typeViewSelected|typeViewTextChanged|typeViewTextSelectionChanged|typeViewTextTraversedAtMovementGranularity|typeWindowContentChanged|typeWindowsChanged|typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagRetrieveInteractiveWindows|flagIncludeNotImportantViews|flagReportViewIds|flagRequestEnhancedWebAccessibility"
android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility"
android:canPerformGestures="true"
android:canRequestEnhancedWebAccessibility="true"
android:canRetrieveWindowContent="true"
android:description="@string/text_accessibility_service_description"
android:notificationTimeout="0"/>
android:notificationTimeout="100"/>

View File

@@ -36,6 +36,8 @@ import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.
public class UiObject extends AccessibilityNodeInfoCompat {
public static final int ACTION_APPEND_TEXT = 0x00200001;
private static final String TAG = "UiObject";
private static final boolean DEBUG = false;
private static int notRecycledCount = 0;

View File

@@ -42,14 +42,18 @@ public class ActionFactory {
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static SimpleAction createActionWithEditableFilter(int action, int index, final String text) {
public static SimpleAction createActionWithEditableFilter(final int action, int index, final String text) {
return new SearchTargetAction(action, new FilterAction.EditableFilter(index)) {
@Override
protected void performAction(UiObject node) {
Bundle args = new Bundle();
args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, node.text() + text);
node.performAction(getAction(), args);
if (action == AccessibilityNodeInfo.ACTION_SET_TEXT) {
args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
} else {
args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, node.text() + text);
}
node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args);
}
};
}

View File

@@ -1,35 +0,0 @@
package com.stardust.uiautomator;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.InstrumentationInfo;
import android.widget.Toast;
import java.util.List;
/**
* Created by Stardust on 2017/5/9.
*/
public class Test {
private void runTests(Context context) {
final String packageName = context.getPackageName();
final List<InstrumentationInfo> list =
context.getPackageManager().queryInstrumentation(packageName, 0);
if (list.isEmpty()) {
Toast.makeText(context, "Cannot find instrumentation for " + packageName,
Toast.LENGTH_SHORT).show();
return;
}
final InstrumentationInfo instrumentationInfo = list.get(0);
final ComponentName componentName =
new ComponentName(instrumentationInfo.packageName,
instrumentationInfo.name);
if (!context.startInstrumentation(componentName, null, null)) {
Toast.makeText(context, "Cannot run instrumentation for " + packageName,
Toast.LENGTH_SHORT).show();
}
}
}

View File

@@ -59,13 +59,14 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
@Override
public void onAccessibilityEvent(final AccessibilityEvent event) {
Log.v(TAG, "onAccessibilityEvent: " + event);
try {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|| event.getEventType() == AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
|| event.getEventType() == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
AccessibilityNodeInfo root = super.getRootInActiveWindow();
Log.v(TAG, "getRootInActiveWindow: " + root);
if (root != null)
if (root != null) {
mRootInActiveWindow = root;
} catch (Exception ignored) {
Log.d(TAG, "rootInActiveWindow: " + mRootInActiveWindow);
}
}
if (!containsAllEventTypes && !eventTypes.contains(event.getEventType()))
return;
@@ -81,6 +82,7 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
}
}
@Override
public void onInterrupt() {

View File

@@ -27,5 +27,5 @@ dependencies {
})
testCompile 'junit:junit:4.12'
compile 'com.android.support:support-annotations:25.3.1'
compile 'com.github.czy1121:settingscompat:1.1.4'
compile 'com.github.hyb1996:settingscompat:1.1.5'
}

View File

@@ -0,0 +1,76 @@
package com.stardust.util;
import android.content.Intent;
import android.util.SparseArray;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Stardust on 2017/7/11.
*/
public class IntentExtras implements Serializable {
private static int mMaxId = -1;
private static final String EXTRA_ID = "com.stardust.util.IntentExtras.id";
private static SparseArray<Map<String, Object>> extraStore = new SparseArray<>();
public static IntentExtras newExtras() {
return new IntentExtras();
}
public static IntentExtras fromIntent(Intent intent) {
int id = intent.getIntExtra(EXTRA_ID, -1);
if (id < 0) {
throw new IllegalArgumentException("");
}
return new IntentExtras(id);
}
private Map<String, Object> mMap;
private int mId;
private IntentExtras() {
mMap = new HashMap<>();
mMaxId++;
mId = mMaxId;
extraStore.put(mId, mMap);
}
private IntentExtras(int id) {
mMap = extraStore.get(id);
mMaxId = id;
}
@SuppressWarnings("unchecked")
public <T> T get(String key) {
return (T) mMap.get(key);
}
@SuppressWarnings("unchecked")
public <T> T getAndClear(String key) {
T value = (T) mMap.get(key);
clear();
return value;
}
public IntentExtras put(String key, Object value) {
mMap.put(key, value);
return this;
}
public Intent putInIntent(Intent intent) {
intent.putExtra(EXTRA_ID, mMaxId);
return intent;
}
public void clear() {
extraStore.remove(mId);
mMap = null;
}
}

View File

@@ -49,6 +49,19 @@ public class ScreenMetrics {
return y * deviceScreenHeight / height;
}
public static int rescaleX(int x, int width) {
if (width == 0 || !initialized)
return x;
return x * width / deviceScreenWidth;
}
public static int rescaleY(int y, int height) {
if (height == 0 || !initialized)
return y;
return y * height / deviceScreenHeight;
}
private int mScreenWidth;
private int mScreenHeight;